-
Notifications
You must be signed in to change notification settings - Fork 274
Add malloc-may-fail option to goto-check #5212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,6 @@ main.c | |
^EXIT=10$ | ||
^SIGNAL=0$ | ||
^VERIFICATION FAILED$ | ||
^\*\* 2 of 15 | ||
^\*\* 2 of 16 | ||
-- | ||
^warning: ignoring |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include <stdlib.h> | ||
|
||
int main() | ||
{ | ||
char *p = malloc(100); | ||
assert(p); // should fail, given the malloc-may-fail option | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
main.c | ||
--malloc-may-fail --malloc-fail-null | ||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
^\[main.assertion.\d+\] line \d+ assertion p: FAILURE$ | ||
^VERIFICATION FAILED$ | ||
-- | ||
^warning: ignoring | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏️ in future, we've found it helpful in test-gen to include a description explaining the purpose of the test below the line. for all tests. It helps when a test fails to understand why does it even exist. E.g
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
main.c | ||
|
||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^\[main.assertion.\d+\] line \d+ assertion p: SUCCESS$ | ||
^VERIFICATION SUCCESSFUL$ | ||
-- | ||
^warning: ignoring |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,6 +75,31 @@ __CPROVER_HIDE:; | |
__CPROVER_size_t alloc_size = nmemb * size; | ||
#pragma CPROVER check pop | ||
|
||
if(__CPROVER_malloc_failure_mode == __CPROVER_malloc_failure_mode_return_null) | ||
{ | ||
__CPROVER_bool should_malloc_fail = __VERIFIER_nondet___CPROVER_bool(); | ||
if( | ||
alloc_size > __CPROVER_max_malloc_size || | ||
(__CPROVER_malloc_may_fail && should_malloc_fail)) | ||
{ | ||
return (void *)0; | ||
} | ||
} | ||
else if( | ||
__CPROVER_malloc_failure_mode == | ||
__CPROVER_malloc_failure_mode_assert_then_assume) | ||
{ | ||
__CPROVER_assert( | ||
alloc_size <= __CPROVER_max_malloc_size, "max allocation size exceeded"); | ||
__CPROVER_assume(alloc_size <= __CPROVER_max_malloc_size); | ||
|
||
__CPROVER_bool should_malloc_fail = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_assert( | ||
!__CPROVER_malloc_may_fail || !should_malloc_fail, | ||
"max allocation may fail"); | ||
__CPROVER_assume(!__CPROVER_malloc_may_fail || !should_malloc_fail); | ||
} | ||
|
||
void *malloc_res; | ||
// realistically, calloc may return NULL, | ||
// and __CPROVER_allocate doesn't, but no one cares | ||
|
@@ -112,50 +137,55 @@ __CPROVER_bool __VERIFIER_nondet___CPROVER_bool(); | |
|
||
inline void *malloc(__CPROVER_size_t malloc_size) | ||
{ | ||
// realistically, malloc may return NULL, | ||
// and __CPROVER_allocate doesn't, but no one cares | ||
__CPROVER_HIDE:; | ||
// realistically, malloc may return NULL, | ||
// but we only do so if `--malloc-may-fail` is set | ||
__CPROVER_HIDE:; | ||
|
||
if(__CPROVER_malloc_failure_mode == __CPROVER_malloc_failure_mode_return_null) | ||
{ | ||
__CPROVER_bool should_malloc_fail = __VERIFIER_nondet___CPROVER_bool(); | ||
if( | ||
__CPROVER_malloc_failure_mode == | ||
__CPROVER_malloc_failure_mode_return_null) | ||
malloc_size > __CPROVER_max_malloc_size || | ||
(__CPROVER_malloc_may_fail && should_malloc_fail)) | ||
{ | ||
if(malloc_size > __CPROVER_max_malloc_size) | ||
{ | ||
return (void *)0; | ||
} | ||
} | ||
else if( | ||
__CPROVER_malloc_failure_mode == | ||
__CPROVER_malloc_failure_mode_assert_then_assume) | ||
{ | ||
__CPROVER_assert( | ||
malloc_size <= __CPROVER_max_malloc_size, | ||
"max allocation size exceeded"); | ||
__CPROVER_assume(malloc_size <= __CPROVER_max_malloc_size); | ||
return (void *)0; | ||
} | ||
} | ||
else if( | ||
__CPROVER_malloc_failure_mode == | ||
__CPROVER_malloc_failure_mode_assert_then_assume) | ||
{ | ||
__CPROVER_assert( | ||
malloc_size <= __CPROVER_max_malloc_size, "max allocation size exceeded"); | ||
__CPROVER_assume(malloc_size <= __CPROVER_max_malloc_size); | ||
|
||
__CPROVER_bool should_malloc_fail = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_assert( | ||
!__CPROVER_malloc_may_fail || !should_malloc_fail, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don’t think it makes a lot of sense to have the assertion here in this form, this will always fail the way it is written. |
||
"max allocation may fail"); | ||
__CPROVER_assume(!__CPROVER_malloc_may_fail || !should_malloc_fail); | ||
} | ||
|
||
void *malloc_res; | ||
malloc_res = __CPROVER_allocate(malloc_size, 0); | ||
void *malloc_res; | ||
malloc_res = __CPROVER_allocate(malloc_size, 0); | ||
|
||
// make sure it's not recorded as deallocated | ||
__CPROVER_deallocated = | ||
(malloc_res == __CPROVER_deallocated) ? 0 : __CPROVER_deallocated; | ||
// make sure it's not recorded as deallocated | ||
__CPROVER_deallocated = | ||
(malloc_res == __CPROVER_deallocated) ? 0 : __CPROVER_deallocated; | ||
|
||
// record the object size for non-determistic bounds checking | ||
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_malloc_object = | ||
record_malloc ? malloc_res : __CPROVER_malloc_object; | ||
__CPROVER_malloc_size = record_malloc ? malloc_size : __CPROVER_malloc_size; | ||
__CPROVER_malloc_is_new_array = | ||
record_malloc ? 0 : __CPROVER_malloc_is_new_array; | ||
// record the object size for non-determistic bounds checking | ||
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_malloc_object = | ||
record_malloc ? malloc_res : __CPROVER_malloc_object; | ||
__CPROVER_malloc_size = record_malloc ? malloc_size : __CPROVER_malloc_size; | ||
__CPROVER_malloc_is_new_array = | ||
record_malloc ? 0 : __CPROVER_malloc_is_new_array; | ||
|
||
// detect memory leaks | ||
__CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_memory_leak = | ||
record_may_leak ? malloc_res : __CPROVER_memory_leak; | ||
// detect memory leaks | ||
__CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool(); | ||
__CPROVER_memory_leak = record_may_leak ? malloc_res : __CPROVER_memory_leak; | ||
|
||
return malloc_res; | ||
return malloc_res; | ||
} | ||
|
||
/* FUNCTION: __builtin_alloca */ | ||
|
@@ -446,7 +476,8 @@ inline void *realloc(void *ptr, __CPROVER_size_t malloc_size) | |
// this shouldn't move if the new size isn't bigger | ||
void *res; | ||
res=malloc(malloc_size); | ||
__CPROVER_array_copy(res, ptr); | ||
if(res != (void *)0) | ||
__CPROVER_array_copy(res, ptr); | ||
free(ptr); | ||
|
||
return res; | ||
|
Uh oh!
There was an error while loading. Please reload this page.