Skip to content

Commit b4b815f

Browse files
peterschrammeltautschnig
authored andcommitted
Add memory leak instrumentation to abort and exit
SV-COMP (also) requires that all dynamically allocated memory is freed via `free` before terminating the program.
1 parent b58a1a5 commit b4b815f

File tree

9 files changed

+69
-1
lines changed

9 files changed

+69
-1
lines changed

doc/man/cbmc.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ enable pointer checks
178178
\fB\-\-memory\-leak\-check\fR
179179
enable memory leak checks
180180
.TP
181+
\fB\-\-memory\-cleanup\-check\fR
182+
Enable memory cleanup checks: assert that all dynamically allocated memory is
183+
explicitly freed before terminating the program.
184+
.TP
181185
\fB\-\-div\-by\-zero\-check\fR
182186
enable division by zero checks
183187
.TP

doc/man/goto-analyzer.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,10 @@ enable pointer checks
506506
\fB\-\-memory\-leak\-check\fR
507507
enable memory leak checks
508508
.TP
509+
\fB\-\-memory\-cleanup\-check\fR
510+
Enable memory cleanup checks: assert that all dynamically allocated memory is
511+
explicitly freed before terminating the program.
512+
.TP
509513
\fB\-\-div\-by\-zero\-check\fR
510514
enable division by zero checks
511515
.TP

doc/man/goto-diff.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ enable pointer checks
4747
\fB\-\-memory\-leak\-check\fR
4848
enable memory leak checks
4949
.TP
50+
\fB\-\-memory\-cleanup\-check\fR
51+
Enable memory cleanup checks: assert that all dynamically allocated memory is
52+
explicitly freed before terminating the program.
53+
.TP
5054
\fB\-\-div\-by\-zero\-check\fR
5155
enable division by zero checks
5256
.TP

doc/man/goto-instrument.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ enable pointer checks
187187
\fB\-\-memory\-leak\-check\fR
188188
enable memory leak checks
189189
.TP
190+
\fB\-\-memory\-cleanup\-check\fR
191+
Enable memory cleanup checks: assert that all dynamically allocated memory is
192+
explicitly freed before terminating the program.
193+
.TP
190194
\fB\-\-div\-by\-zero\-check\fR
191195
enable division by zero checks
192196
.TP
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdlib.h>
2+
3+
extern void __VERIFIER_error();
4+
5+
int main()
6+
{
7+
int *p = malloc(sizeof(int));
8+
if(*p == 0)
9+
abort();
10+
if(*p == 1)
11+
exit(1);
12+
if(*p == 2)
13+
_Exit(1);
14+
if(*p == 3)
15+
__VERIFIER_error();
16+
free(p);
17+
return 0;
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--memory-leak-check --memory-cleanup-check --no-assertions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
_Exit\.memory-leak\.1.*FAILURE
8+
__CPROVER__start\.memory-leak\.1.*SUCCESS
9+
abort\.memory-leak\.1.*FAILURE
10+
exit\.memory-leak\.1.*FAILURE
11+
main\.memory-leak\.1.*FAILURE
12+
--
13+
main\.assertion\.1.*FAILURE
14+
^warning: ignoring

src/ansi-c/goto_check_c.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class goto_check_ct
5555
enable_bounds_check = _options.get_bool_option("bounds-check");
5656
enable_pointer_check = _options.get_bool_option("pointer-check");
5757
enable_memory_leak_check = _options.get_bool_option("memory-leak-check");
58+
enable_memory_cleanup_check =
59+
_options.get_bool_option("memory-cleanup-check");
5860
enable_div_by_zero_check = _options.get_bool_option("div-by-zero-check");
5961
enable_enum_range_check = _options.get_bool_option("enum-range-check");
6062
enable_signed_overflow_check =
@@ -257,6 +259,7 @@ class goto_check_ct
257259
bool enable_bounds_check;
258260
bool enable_pointer_check;
259261
bool enable_memory_leak_check;
262+
bool enable_memory_cleanup_check;
260263
bool enable_div_by_zero_check;
261264
bool enable_enum_range_check;
262265
bool enable_signed_overflow_check;
@@ -276,6 +279,7 @@ class goto_check_ct
276279
{"bounds-check", &enable_bounds_check},
277280
{"pointer-check", &enable_pointer_check},
278281
{"memory-leak-check", &enable_memory_leak_check},
282+
{"memory-cleanup-check", &enable_memory_cleanup_check},
279283
{"div-by-zero-check", &enable_div_by_zero_check},
280284
{"enum-range-check", &enable_enum_range_check},
281285
{"signed-overflow-check", &enable_signed_overflow_check},
@@ -2219,6 +2223,19 @@ void goto_check_ct::goto_check(
22192223
// this has no successor
22202224
assertions.clear();
22212225
}
2226+
else if(i.is_assume())
2227+
{
2228+
// These are further 'exit points' of the program
2229+
const exprt simplified_guard = simplify_expr(i.condition(), ns);
2230+
if(
2231+
enable_memory_cleanup_check && simplified_guard.is_false() &&
2232+
(function_identifier == "abort" || function_identifier == "exit" ||
2233+
function_identifier == "_Exit" ||
2234+
(i.labels.size() == 1 && i.labels.front() == "__VERIFIER_abort")))
2235+
{
2236+
memory_leak_check(function_identifier);
2237+
}
2238+
}
22222239
else if(i.is_dead())
22232240
{
22242241
if(enable_pointer_check || enable_pointer_primitive_check)

src/ansi-c/goto_check_c.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void goto_check_c(
3838
message_handlert &message_handler);
3939

4040
#define OPT_GOTO_CHECK \
41-
"(bounds-check)(pointer-check)(memory-leak-check)" \
41+
"(bounds-check)(pointer-check)(memory-leak-check)(memory-cleanup-check)" \
4242
"(div-by-zero-check)(enum-range-check)" \
4343
"(signed-overflow-check)(unsigned-overflow-check)" \
4444
"(pointer-overflow-check)(conversion-check)(undefined-shift-check)" \
@@ -54,6 +54,7 @@ void goto_check_c(
5454
" --bounds-check enable array bounds checks\n" \
5555
" --pointer-check enable pointer checks\n" /* NOLINT(whitespace/line_length) */ \
5656
" --memory-leak-check enable memory leak checks\n" \
57+
" --memory-cleanup-check enable memory cleanup checks\n" \
5758
" --div-by-zero-check enable division by zero checks\n" \
5859
" --signed-overflow-check enable signed arithmetic over- and underflow checks\n" /* NOLINT(whitespace/line_length) */ \
5960
" --unsigned-overflow-check enable arithmetic over- and underflow checks\n" /* NOLINT(whitespace/line_length) */ \
@@ -75,6 +76,7 @@ void goto_check_c(
7576
options.set_option("bounds-check", cmdline.isset("bounds-check")); \
7677
options.set_option("pointer-check", cmdline.isset("pointer-check")); \
7778
options.set_option("memory-leak-check", cmdline.isset("memory-leak-check")); \
79+
options.set_option("memory-cleanup-check", cmdline.isset("memory-cleanup-check")); /* NOLINT(whitespace/line_length) */ \
7880
options.set_option("div-by-zero-check", cmdline.isset("div-by-zero-check")); \
7981
options.set_option("enum-range-check", cmdline.isset("enum-range-check")); \
8082
options.set_option("signed-overflow-check", cmdline.isset("signed-overflow-check")); /* NOLINT(whitespace/line_length) */ \

src/goto-programs/builtin_functions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,7 @@ void goto_convertt::do_function_call_symbol(
831831
annotated_location = function.source_location();
832832
annotated_location.set("user-provided", true);
833833
dest.add(goto_programt::make_assumption(false_exprt(), annotated_location));
834+
dest.instructions.back().labels.push_back("__VERIFIER_abort");
834835
}
835836
else if(
836837
identifier == "assert" &&

0 commit comments

Comments
 (0)