Skip to content

Commit c7a0d53

Browse files
committed
Re-implement inside stdlib.c
will be squashed. Note: this also introduces some new overflow checks. Also the pre-structhack in test `cbmc/Pointer_byte_extract5` no longer works with `--no-simplify`. But as the issue #5213 shows, CBMC has a much bigger problem with that. So we propose the rewrite the test to use the standard, flexible-array, approach.
1 parent 0c2c362 commit c7a0d53

File tree

15 files changed

+34
-42
lines changed

15 files changed

+34
-42
lines changed

regression/cbmc/Pointer_byte_extract5/main.i

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ typedef union
1111
typedef struct
1212
{
1313
int Count;
14-
Union List[1];
14+
Union List[0];
1515
} Struct3;
1616
#pragma pack(pop)
1717

1818
int main()
1919
{
20-
Struct3 *p = malloc(sizeof(Struct3) + sizeof(Union));
20+
Struct3 *p = malloc(sizeof(Struct3) + 2 * sizeof(Union));
2121
p->Count = 3;
2222
int po=0;
2323

regression/cbmc/Pointer_byte_extract5/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ main.i
44
^EXIT=10$
55
^SIGNAL=0$
66
array\.List dynamic object upper bound in p->List\[2\]: FAILURE
7-
\*\* 1 of 11 failed
7+
\*\* 1 of 12 failed
88
--
99
^warning: ignoring
1010
--

regression/cbmc/malloc-too-large/largest_representable.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ int main()
88
size_t object_bits = 8; // by default
99
size_t cbmc_max_alloc_size = ((size_t)1 << (pointer_width - object_bits)) - 1;
1010
int *p = malloc(cbmc_max_alloc_size); // try to allocate exactly the max
11+
assert(p);
1112

1213
return 0;
1314
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
largest_representable.c
3-
--malloc-size-check
3+
44
^EXIT=0$
55
^SIGNAL=0$
6-
^\[malloc.max_allocation_check.\d+\] line \d+ malloc_size < 2 \^ \(pointer_width - object_id_width\) in ALLOCATE\(malloc_size, 0 != 0\): SUCCESS$
6+
^\[main.assertion.\d+\] line \d+ assertion p: SUCCESS$
77
^VERIFICATION SUCCESSFUL$
88
--
99
^warning: ignoring
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
max_size.c
3-
--malloc-size-check
3+
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[malloc.max_allocation_check.\d+\] line \d+ malloc_size < 2 \^ \(pointer_width - object_id_width\) in ALLOCATE\(malloc_size, 0 != 0\): FAILURE$
6+
^\[main.assertion.\d+\] line \d+ assertion p: FAILURE$
77
^VERIFICATION FAILED$
88
--
99
^warning: ignoring

regression/cbmc/malloc-too-large/one_byte_too_large.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ int main()
99
size_t cbmc_max_alloc_size = ((size_t)1 << (pointer_width - object_bits)) - 1;
1010
// try to allocate the smallest violating amount
1111
int *p = malloc(cbmc_max_alloc_size + 1);
12+
assert(p);
1213

1314
return 0;
1415
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
one_byte_too_large.c
3-
--malloc-size-check
3+
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[malloc.max_allocation_check.\d+\] line \d+ malloc_size < 2 \^ \(pointer_width - object_id_width\) in ALLOCATE\(malloc_size, 0 != 0\): FAILURE$
6+
^\[main.assertion.\d+\] line \d+ assertion p: FAILURE$
77
^VERIFICATION FAILED$
88
--
99
^warning: ignoring

regression/cbmc/pointer-overflow1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ main.c
55
^SIGNAL=0$
66
^\[main\.overflow\.\d+\] line \d+ (pointer )?arithmetic overflow on .*sizeof\(signed int\) .* : SUCCESS
77
^VERIFICATION FAILED$
8-
^\*\* 8 of 11 failed
8+
^\*\* 8 of 12 failed
99
--
1010
^\[main\.overflow\.\d+\] line \d+ (pointer )?arithmetic overflow on .*sizeof\(signed int\) .* : FAILURE
1111
^warning: ignoring

regression/cbmc/r_w_ok1/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ int main()
1616
assert(__CPROVER_w_ok(p, sizeof(int)));
1717

1818
size_t n;
19+
20+
// n is arbitrary but no larger than what CBMC can represent
21+
size_t pointer_width = sizeof(void *) * 8;
22+
size_t object_bits = 8; // by default
23+
size_t cbmc_max_alloc_size = ((size_t)1 << (pointer_width - object_bits)) - 1;
24+
__CPROVER_assume(n<=cbmc_max_alloc_size);
25+
1926
char *arbitrary_size = malloc(n);
2027

2128
assert(__CPROVER_r_ok(arbitrary_size, n));

src/analyses/goto_check.cpp

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ class goto_checkt
7272
enable_built_in_assertions=_options.get_bool_option("built-in-assertions");
7373
enable_assumptions=_options.get_bool_option("assumptions");
7474
error_labels=_options.get_list_option("error-label");
75-
enable_malloc_size_check = _options.get_bool_option("malloc-size-check");
7675
}
7776

7877
typedef goto_functionst::goto_functiont goto_functiont;
@@ -239,7 +238,6 @@ class goto_checkt
239238
bool enable_assertions;
240239
bool enable_built_in_assertions;
241240
bool enable_assumptions;
242-
bool enable_malloc_size_check;
243241

244242
typedef optionst::value_listt error_labelst;
245243
error_labelst error_labels;
@@ -1943,30 +1941,6 @@ void goto_checkt::goto_check(
19431941
if(rw_ok_cond.has_value())
19441942
rhs = *rw_ok_cond;
19451943
}
1946-
1947-
if(enable_malloc_size_check && code_assign.rhs().id() == ID_side_effect)
1948-
{
1949-
const auto &rhs_side_effect = to_side_effect_expr(code_assign.rhs());
1950-
if(rhs_side_effect.get_statement() == ID_allocate)
1951-
{
1952-
const auto &alloc_size_type = rhs_side_effect.op0().type();
1953-
const auto pointer_bits =
1954-
from_integer(config.ansi_c.pointer_width, alloc_size_type);
1955-
const auto object_bits =
1956-
from_integer(config.bv_encoding.object_bits, alloc_size_type);
1957-
const auto max_alloc_size =
1958-
binary_exprt{from_integer(2, alloc_size_type),
1959-
ID_power,
1960-
minus_exprt{pointer_bits, object_bits}};
1961-
add_guarded_property(
1962-
binary_relation_exprt{rhs_side_effect.op0(), ID_lt, max_alloc_size},
1963-
"malloc_size < 2 ^ (pointer_width - object_id_width)",
1964-
"max allocation check",
1965-
i.code.source_location(),
1966-
code_assign.rhs(),
1967-
guardt{true_exprt{}, guard_manager});
1968-
}
1969-
}
19701944
}
19711945
else if(i.is_function_call())
19721946
{

src/analyses/goto_check.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ void goto_check(
3838
"(div-by-zero-check)(enum-range-check)(signed-overflow-check)(unsigned-" \
3939
"overflow-check)" \
4040
"(pointer-overflow-check)(conversion-check)(undefined-shift-check)" \
41-
"(float-overflow-check)(nan-check)(no-built-in-assertions)" \
42-
"(malloc-size-check)"
41+
"(float-overflow-check)(nan-check)(no-built-in-assertions)"
4342

4443
// clang-format off
4544
#define HELP_GOTO_CHECK \
@@ -56,7 +55,6 @@ void goto_check(
5655
" --nan-check check floating-point for NaN\n" \
5756
" --no-built-in-assertions ignore assertions in built-in library\n" \
5857
" --enum-range-check checks that all enum type expressions have values in the enum range\n" /* NOLINT(whitespace/line_length) */ \
59-
" --malloc-size-check check that CBMC can represent the allocated object of requested size" /* NOLINT(whitespace/line_length) */ \
6058
// clang-format on
6159

6260
#define PARSE_OPTIONS_GOTO_CHECK(cmdline, options) \
@@ -72,7 +70,6 @@ void goto_check(
7270
options.set_option("undefined-shift-check", cmdline.isset("undefined-shift-check")); /* NOLINT(whitespace/line_length) */ \
7371
options.set_option("float-overflow-check", cmdline.isset("float-overflow-check")); /* NOLINT(whitespace/line_length) */ \
7472
options.set_option("nan-check", cmdline.isset("nan-check")); \
75-
options.set_option("built-in-assertions", !cmdline.isset("no-built-in-assertions")); /* NOLINT(whitespace/line_length) */ \
76-
options.set_option("malloc-size-check", cmdline.isset("malloc-size-check"))
73+
options.set_option("built-in-assertions", !cmdline.isset("no-built-in-assertions")); /* NOLINT(whitespace/line_length) */
7774

7875
#endif // CPROVER_ANALYSES_GOTO_CHECK_H

src/ansi-c/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ endforeach()
1313

1414
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cprover_library.inc"
1515
COMMAND converter < ${converter_input_path} > "${CMAKE_CURRENT_BINARY_DIR}/cprover_library.inc"
16-
DEPENDS converter
16+
DEPENDS converter ${converter_input_path}
1717
)
1818

1919
add_executable(file_converter file_converter.cpp)

src/ansi-c/ansi_c_internal_additions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ void ansi_c_internal_additions(std::string &code)
155155
"void *" CPROVER_PREFIX "allocate("
156156
CPROVER_PREFIX "size_t size, " CPROVER_PREFIX "bool zero);\n"
157157
"const void *" CPROVER_PREFIX "alloca_object = 0;\n"
158+
CPROVER_PREFIX "size_t " CPROVER_PREFIX "pointer_width="+
159+
std::to_string(config.ansi_c.pointer_width)+";\n"
160+
CPROVER_PREFIX "size_t " CPROVER_PREFIX "object_bits="+
161+
std::to_string(config.bv_encoding.object_bits)+";\n"
158162

159163
// this is ANSI-C
160164
"extern " CPROVER_PREFIX "thread_local const char __func__["

src/ansi-c/library/cprover.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ extern const void *__CPROVER_malloc_object;
1616
extern __CPROVER_size_t __CPROVER_malloc_size;
1717
extern _Bool __CPROVER_malloc_is_new_array;
1818
extern const void *__CPROVER_memory_leak;
19+
extern __CPROVER_size_t __CPROVER_pointer_width;
20+
extern __CPROVER_size_t __CPROVER_object_bits;
1921

2022
void __CPROVER_assume(__CPROVER_bool assumption) __attribute__((__noreturn__));
2123
void __CPROVER_assert(__CPROVER_bool assertion, const char *description);

src/ansi-c/library/stdlib.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ inline void *malloc(__CPROVER_size_t malloc_size)
115115
// realistically, malloc may return NULL,
116116
// and __CPROVER_allocate doesn't, but no one cares
117117
__CPROVER_HIDE:;
118+
119+
if(
120+
malloc_size >= ((__CPROVER_size_t)1
121+
<< (__CPROVER_pointer_width - __CPROVER_object_bits)))
122+
return (void *)0;
123+
118124
void *malloc_res;
119125
malloc_res = __CPROVER_allocate(malloc_size, 0);
120126

0 commit comments

Comments
 (0)