Description
For the following program, we get VERIFICATION_SUCCESFUL
, although the assertion should give a FAILURE
:
soundness_r_ok.c
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int sum(int s[], int size)
{
// Assume the size is valid
//__CPROVER_assume(size >= 0);
__CPROVER_assume(size==3);
// Assume that 's' has at least 'size' valid elements
// This prevents out-of-bounds access
__CPROVER_assume(__CPROVER_r_ok(s, size * sizeof(int)));
int res = 0;
int i = 0;
// EDIT: Commenting out loop does not change the outcome
do {
res += s[i];
i++;
} while (i < size);
assert(false);
return res;
}
The assertion false should be reachable with the assumptions but we get:
$ cbmc soundness_r_ok.c --function sum
CBMC version 6.5.0 (cbmc-6.5.0-2-gcd39b3a97e) 64-bit x86_64 linux
...
[sum.assertion.1] line 23 assertion false: SUCCESS
** 0 of 13 failed (1 iterations)
VERIFICATION SUCCESSFUL
Expected:
[sum.assertion.1] line 23 assertion false: FAILURE
VERIFICATION FAILED
Background: With assume size==3
we check only one path of symbolic execution. My student @yosephinestwn is currently implementing an extension to CBMC, to verify just one path, we call that retracing (https://github.com/yosephinestwn/cbmc). To test the implementation, she started a version without the assume size==3
but with the newly implemented option --retrace 110
to follow the control flow trace. This control flow trace corresponds to the branching in the GOTO program and in our case, we have just one goto instruction IF sum::1::i < sum::size THEN GOTO 1
. The --retrace 110
means the GOTO target branch is taken twice (the 11) and not taken for the third time (the 0), afterwards, assert false should give a verification failure. After trying to fix our implementation, we found out that the problem is already in the upstream CBMC with assume size==3
.