Skip to content

Commit bbb1ce8

Browse files
authored
Merge pull request #4270 from tautschnig/alloca-free
Detect use of free() with alloca-allocated objects
2 parents 8e1cf18 + 3c3348a commit bbb1ce8

File tree

12 files changed

+43
-8
lines changed

12 files changed

+43
-8
lines changed

regression/cbmc/alloca1/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdlib.h>
2+
3+
#ifdef _WIN32
4+
void *alloca(size_t alloca_size);
5+
#endif
6+
7+
int main()
8+
{
9+
int *p = alloca(sizeof(int));
10+
*p = 42;
11+
free(p);
12+
}

regression/cbmc/alloca1/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
free called for stack-allocated object: FAILURE$
8+
^\*\* 1 of 12 failed
9+
--
10+
^warning: ignoring

regression/cbmc/function-return-no-body1/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ activate-multi-line-match
55
^EXIT=10$
66
^SIGNAL=0$
77
VERIFICATION FAILED
8-
<function_call hidden="false" step_nr="18" thread="0">\n\s*<function display_name="no_body" identifier="no_body">
9-
<function_return hidden="false" step_nr="19" thread="0">\n\s*<function display_name="no_body" identifier="no_body">
8+
<function_call hidden="false" step_nr="\d+" thread="0">\n\s*<function display_name="no_body" identifier="no_body">
9+
<function_return hidden="false" step_nr="\d+" thread="0">\n\s*<function display_name="no_body" identifier="no_body">
1010
--
1111
^warning: ignoring

regression/goto-analyzer/constant_propagation_01/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 13, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_02/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_03/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_04/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_07/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 3, assigns: 11, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 9, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_12/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$
7+
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 11, function calls: 2$
88
--
99
^warning: ignoring

src/ansi-c/ansi_c_internal_additions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ void ansi_c_internal_additions(std::string &code)
148148
"const void *" CPROVER_PREFIX "memory_leak=0;\n"
149149
"void *" CPROVER_PREFIX "allocate("
150150
CPROVER_PREFIX "size_t size, " CPROVER_PREFIX "bool zero);\n"
151+
"const void *" CPROVER_PREFIX "alloca_object = 0;\n"
151152

152153
// this is ANSI-C
153154
"extern " CPROVER_PREFIX "thread_local const char __func__["

src/ansi-c/library/stdlib.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ inline void *malloc(__CPROVER_size_t malloc_size)
128128
/* FUNCTION: __builtin_alloca */
129129

130130
__CPROVER_bool __VERIFIER_nondet___CPROVER_bool();
131+
extern void *__CPROVER_alloca_object;
131132

132133
inline void *__builtin_alloca(__CPROVER_size_t alloca_size)
133134
{
@@ -144,6 +145,10 @@ inline void *__builtin_alloca(__CPROVER_size_t alloca_size)
144145
__CPROVER_malloc_size=record_malloc?alloca_size:__CPROVER_malloc_size;
145146
__CPROVER_malloc_is_new_array=record_malloc?0:__CPROVER_malloc_is_new_array;
146147

148+
// record alloca to detect invalid free
149+
__CPROVER_bool record_alloca = __VERIFIER_nondet___CPROVER_bool();
150+
__CPROVER_alloca_object = record_alloca ? res : __CPROVER_alloca_object;
151+
147152
return res;
148153
}
149154

@@ -164,6 +169,7 @@ __CPROVER_HIDE:;
164169
#undef free
165170

166171
__CPROVER_bool __VERIFIER_nondet___CPROVER_bool();
172+
extern void *__CPROVER_alloca_object;
167173

168174
inline void free(void *ptr)
169175
{
@@ -185,6 +191,11 @@ inline void free(void *ptr)
185191
!__CPROVER_malloc_is_new_array,
186192
"free called for new[] object");
187193

194+
// catch people who try to use free(...) with alloca
195+
__CPROVER_precondition(
196+
ptr == 0 || __CPROVER_alloca_object != ptr,
197+
"free called for stack-allocated object");
198+
188199
if(ptr!=0)
189200
{
190201
// non-deterministically record as deallocated

src/cpp/cpp_internal_additions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ void cpp_internal_additions(std::ostream &out)
8585
out << "const void *" CPROVER_PREFIX "memory_leak = 0;" << '\n';
8686
out << "void *" CPROVER_PREFIX "allocate("
8787
<< CPROVER_PREFIX "size_t size, " CPROVER_PREFIX "bool zero);" << '\n';
88+
out << "const void *" CPROVER_PREFIX "alloca_object = 0;" << '\n';
8889

8990
// auxiliaries for new/delete
9091
out << "void *__new(__CPROVER::size_t);" << '\n';

0 commit comments

Comments
 (0)