Description
CBMC version: develop
Operating system: Mac OS 10.15.7
I know it's recommended not to use __CPROVER_r_ok
within __CPROVER_assume
, but it's not enforced -- no error from CBMC.
Some projects (e.g. throughout s2n) use this, and the point of this test case is to demonstrate that CBMC would accept bad programs when __CPROVER_r_ok
is used in __CPROVER_assume
, and give a false guarantee of correctness even with all of the pointer-checking flags enabled.
Test case:
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
bool validate(const char *data, bool allocated)
{
bool check_1 = (data == NULL) ==> (!allocated);
bool check_2 = allocated ==> __CPROVER_r_ok(data, 128);
return check_1 && check_2;
}
void main()
{
char *data;
bool allocated;
data = !allocated ? NULL : malloc(1);
__CPROVER_assume(validate(data, allocated));
// same as `validate`, but inlined here to see which assertion fails
assert((data == NULL) ==> (!allocated));
assert(allocated ==> __CPROVER_r_ok(data, 128));
}
Exact command line resulting in the issue:
cbmc --malloc-may-fail --malloc-fail-null --pointer-primitive-check --bounds-check --pointer-check --pointer-overflow-check test.c
What behaviour did you expect:
The second assert
should fail because data
is malloc
ed with 1 byte and shouldn't be readable up to 128 bytes.
What happened instead:
CBMC reports that the program is valid -- all implicit and explicit assertions pass. I have used all the CBMC -check
flags that I thought could be relevant in this context.
Additional information:
With the --smt2
flag, CBMC does report an assertion failure at the last line of main
and also within the __CPROVER_r_ok
check, as expected.
This bug is related to, but is different from, #5952. There we actually read the same length as we allocated, so the failure from --smt2
is unexpected. In this report, success from the SAT-based solver is unexpected.