Skip to content

Commit c8b29ff

Browse files
committed
Add new --allocate-size-check option to goto_check()
The option adds an assertion to check that not more memory is allocated with __CPROVER_allocate() than cbmc can address. Since the primitive is used by the models of malloc(), etc., this also guarantees that those function don't allocate more memory than can be addressed.
1 parent 037e860 commit c8b29ff

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/analyses/goto_check.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class goto_checkt
7575
error_labels=_options.get_list_option("error-label");
7676
enable_pointer_primitive_check =
7777
_options.get_bool_option("pointer-primitive-check");
78+
enable_allocate_size_check =
79+
_options.get_bool_option("allocate-size-check");
7880
}
7981

8082
typedef goto_functionst::goto_functiont goto_functiont;
@@ -195,6 +197,8 @@ class goto_checkt
195197
/// \param guard: the condition under which the operation happens
196198
void pointer_primitive_check(const exprt &expr, const guardt &guard);
197199

200+
void allocate_size_check(const side_effect_exprt &expr, const guardt &guard);
201+
198202
/// Returns true if the given expression is a pointer primitive such as
199203
/// __CPROVER_r_ok()
200204
///
@@ -256,6 +260,7 @@ class goto_checkt
256260
bool enable_built_in_assertions;
257261
bool enable_assumptions;
258262
bool enable_pointer_primitive_check;
263+
bool enable_allocate_size_check;
259264

260265
typedef optionst::value_listt error_labelst;
261266
error_labelst error_labels;
@@ -1229,6 +1234,29 @@ void goto_checkt::pointer_primitive_check(
12291234
guard);
12301235
}
12311236

1237+
void goto_checkt::allocate_size_check(
1238+
const side_effect_exprt &expr,
1239+
const guardt &guard)
1240+
{
1241+
if(!enable_allocate_size_check)
1242+
return;
1243+
1244+
const exprt size_expr = expr.operands().front();
1245+
1246+
binary_relation_exprt bre(
1247+
size_expr,
1248+
ID_le,
1249+
ns.lookup(CPROVER_PREFIX "max_malloc_size").symbol_expr());
1250+
1251+
add_guarded_property(
1252+
bre,
1253+
"more memory allocated than can be addressed by cbmc",
1254+
"allocate",
1255+
expr.source_location(),
1256+
expr,
1257+
guard);
1258+
}
1259+
12321260
bool goto_checkt::is_pointer_primitive(const exprt &expr)
12331261
{
12341262
// we don't need to include the __CPROVER_same_object primitive here as it
@@ -1812,6 +1840,15 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard)
18121840
{
18131841
pointer_primitive_check(expr, guard);
18141842
}
1843+
else if(expr.id() == ID_side_effect)
1844+
{
1845+
const auto &side_effect_expr = to_side_effect_expr(expr);
1846+
1847+
if(side_effect_expr.get_statement() == ID_allocate)
1848+
{
1849+
allocate_size_check(side_effect_expr, guard);
1850+
}
1851+
}
18151852
}
18161853

18171854
void goto_checkt::check(const exprt &expr)
@@ -1934,6 +1971,8 @@ void goto_checkt::goto_check(
19341971
flag_resetter.set_flag(enable_nan_check, false);
19351972
else if(d.first == "disable:pointer-primitive-check")
19361973
flag_resetter.set_flag(enable_pointer_primitive_check, false);
1974+
else if(d.first == "disable:allocate-size-check")
1975+
flag_resetter.set_flag(enable_allocate_size_check, false);
19371976
}
19381977

19391978
new_code.clear();

src/analyses/goto_check.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ void goto_check(
3939
"overflow-check)" \
4040
"(pointer-overflow-check)(conversion-check)(undefined-shift-check)" \
4141
"(float-overflow-check)(nan-check)(no-built-in-assertions)" \
42-
"(pointer-primitive-check)"
42+
"(pointer-primitive-check)" \
43+
"(allocate-size-check)"
4344

4445
// clang-format off
4546
#define HELP_GOTO_CHECK \
@@ -56,7 +57,8 @@ void goto_check(
5657
" --nan-check check floating-point for NaN\n" \
5758
" --no-built-in-assertions ignore assertions in built-in library\n" \
5859
" --enum-range-check checks that all enum type expressions have values in the enum range\n" /* NOLINT(whitespace/line_length) */ \
59-
" --pointer-primitive-check checks that all pointers in pointer primitives are valid or null\n" /* NOLINT(whitespace/line_length) */
60+
" --pointer-primitive-check checks that all pointers in pointer primitives are valid or null\n" /* NOLINT(whitespace/line_length) */ \
61+
" --allocate-size-check checks that not more memory is allocated than can be addressed by cbmc" /* NOLINT(whitespace/line_length) */
6062

6163
#define PARSE_OPTIONS_GOTO_CHECK(cmdline, options) \
6264
options.set_option("bounds-check", cmdline.isset("bounds-check")); \
@@ -72,7 +74,8 @@ void goto_check(
7274
options.set_option("float-overflow-check", cmdline.isset("float-overflow-check")); /* NOLINT(whitespace/line_length) */ \
7375
options.set_option("nan-check", cmdline.isset("nan-check")); \
7476
options.set_option("built-in-assertions", !cmdline.isset("no-built-in-assertions")); /* NOLINT(whitespace/line_length) */ \
75-
options.set_option("pointer-primitive-check", cmdline.isset("pointer-primitive-check")) /* NOLINT(whitespace/line_length) */
77+
options.set_option("pointer-primitive-check", cmdline.isset("pointer-primitive-check")); /* NOLINT(whitespace/line_length) */ \
78+
options.set_option("allocate-size-check", cmdline.isset("allocate-size-check")) /* NOLINT(whitespace/line_length) */
7679
// clang-format on
7780

7881
#endif // CPROVER_ANALYSES_GOTO_CHECK_H

0 commit comments

Comments
 (0)