-
Notifications
You must be signed in to change notification settings - Fork 277
A new implementation for assigns clauses #6377
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 |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
typedef struct | ||
{ | ||
uint8_t *buf; | ||
size_t size; | ||
} blob; | ||
|
||
void foo(blob *b, uint8_t *value) | ||
// clang-format off | ||
__CPROVER_requires(b->size == 5) | ||
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(b->buf)) | ||
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(value)) | ||
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. This overloaded use of |
||
__CPROVER_ensures(b->buf[0] == 1) | ||
__CPROVER_ensures(b->buf[1] == 1) | ||
__CPROVER_ensures(b->buf[2] == 1) | ||
__CPROVER_ensures(b->buf[3] == 1) | ||
__CPROVER_ensures(b->buf[4] == 1) | ||
// clang-format on | ||
{ | ||
b->buf[0] = *value; | ||
b->buf[1] = *value; | ||
b->buf[2] = *value; | ||
b->buf[3] = *value; | ||
b->buf[4] = *value; | ||
|
||
*value = 2; | ||
} | ||
|
||
int main() | ||
{ | ||
blob b; | ||
b.size = 5; | ||
b.buf = malloc(b.size * (sizeof(*(b.buf)))); | ||
uint8_t value = 1; | ||
|
||
foo(&b, &value); | ||
|
||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
main.c | ||
--enforce-contract foo | ||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
-- | ||
-- | ||
This test checks that POINTER_OBJECT can be used both on arrays and scalars. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,24 @@ | ||
#include <assert.h> | ||
#include <stdlib.h> | ||
|
||
int idx = 4; | ||
int *arr; | ||
|
||
int nextIdx() __CPROVER_assigns(idx) | ||
void f1(int *a, int len) __CPROVER_assigns(*a) | ||
{ | ||
idx++; | ||
return idx; | ||
a[0] = 0; | ||
a[5] = 5; | ||
} | ||
|
||
void f1(int a[], int len) __CPROVER_assigns(*a, idx) | ||
void f2(int *a, int len) __CPROVER_assigns(__CPROVER_POINTER_OBJECT(a)) | ||
{ | ||
a[nextIdx()] = 5; | ||
a[0] = 0; | ||
a[5] = 5; | ||
free(a); | ||
} | ||
|
||
int main() | ||
{ | ||
int arr[10]; | ||
f1(arr, 10); | ||
|
||
assert(idx == 5); | ||
|
||
return 0; | ||
arr = malloc(100 * sizeof(int)); | ||
f1(arr, 100); | ||
f2(arr, 100); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,15 @@ | ||
CORE | ||
main.c | ||
--enforce-contract f1 --enforce-contract nextIdx | ||
^EXIT=0$ | ||
--enforce-contract f1 --enforce-contract f2 | ||
^\[f1.\d+\] line \d+ Check that a\[.*0\] is assignable: SUCCESS$ | ||
^\[f1.\d+\] line \d+ Check that a\[.*5\] is assignable: FAILURE$ | ||
^\[f2.\d+\] line \d+ Check that a\[.*0\] is assignable: SUCCESS$ | ||
^\[f2.\d+\] line \d+ Check that a\[.*5\] is assignable: SUCCESS$ | ||
^\[f2.\d+\] line \d+ Check that POINTER_OBJECT\(\(void \*\)a\) is assignable: SUCCESS$ | ||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
^VERIFICATION FAILED$ | ||
-- | ||
-- | ||
Checks whether the instrumentation process does not duplicate function calls | ||
used as part of array-index operations, i.e., if a function call is used in | ||
the computation of the index of an array assignment, then instrumenting that | ||
statement with an assigns clause will not result in multiple function calls. | ||
This test also ensures that assigns clauses correctly check for global | ||
variables modified by subcalls. | ||
This test ensures that assigns clauses correctly check for global variables, | ||
and access using *ptr vs POINTER_OBJECT(ptr). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ main.c | |
-- | ||
Check that Elvis operator expressions of form '(cond ? *if_true : *if_false)' | ||
are supported in assigns clauses. | ||
|
||
BUG: `is_lvalue` in goto is not consistent with `target.get_bool(ID_C_lvalue)`. | ||
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. We agreed that CBMC is doing the reasonable thing here. I also updated it on the previous PR to 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. We should open a GitHub issue for this bug. This is outside the contract implementation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,5 +17,5 @@ int main() | |
{ | ||
int x; | ||
foo(&x); | ||
return 0; | ||
baz(&x); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
|
||
int baz(int *x) __CPROVER_assigns(__CPROVER_POINTER_OBJECT()) | ||
{ | ||
*x = 0; | ||
return 0; | ||
} | ||
|
||
int main() | ||
{ | ||
int x; | ||
baz(&x); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
CORE | ||
main.c | ||
--enforce-contract baz | ||
^EXIT=(1|64)$ | ||
^SIGNAL=0$ | ||
^.*error: pointer_object expects one argument$ | ||
^CONVERSION ERROR$ | ||
-- | ||
-- | ||
Check that `__CPROVER_POINTER_OBJECT` in assigns clauses are invoked correctly. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
KNOWNBUG | ||
CORE | ||
main.c | ||
--enforce-contract foo | ||
^EXIT=10$ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include <assert.h> | ||
#include <stdlib.h> | ||
|
||
static int x; | ||
|
||
void foo() __CPROVER_assigns(x) | ||
{ | ||
int *y = &x; | ||
|
||
static int x; | ||
x++; | ||
|
||
(*y)++; | ||
} | ||
|
||
int main() | ||
{ | ||
foo(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
CORE | ||
main.c | ||
--enforce-contract foo _ --pointer-primitive-check | ||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS$ | ||
^\[foo.\d+\] line \d+ Check that foo\$\$1\$\$x is assignable: SUCCESS$ | ||
^\[foo.\d+\] line \d+ Check that \*y is assignable: SUCCESS$ | ||
^VERIFICATION SUCCESSFUL$ | ||
-- | ||
-- | ||
Checks whether static local and global variables are correctly tracked | ||
in assigns clause verification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new message is a downgrade in terms of user experience.