This program is proved correct with the SAT backend but fails with with SMT2 backend with --pointer-check --bounds-check:
[stk_push.pointer_dereference.17] line 57 dereference failure: pointer outside object bounds in stk->elems[(signed long int)stk->top]: FAILURE
The analysis using the SMT2 backend succeeds if we change the assumption at line 46:
__CPROVER_assume(UINT8_MAX <= stk_size && stk_size <= UINT8_MAX);
into
__CPROVER_assume(UINT8_MAX == stk_size);
or into an assignment
#include <stdlib.h>
#include <stdint.h>
extern size_t __CPROVER_max_malloc_size;
int __builtin_clzll(unsigned long long);
#define __nof_symex_objects \
((size_t)(1ULL << __builtin_clzll(__CPROVER_max_malloc_size)))
typedef struct {
size_t k;
void **ptrs;
} smap_t;
void smap_init(smap_t *smap, size_t k) {
*smap = (smap_t){
.k = k, .ptrs = __CPROVER_allocate(__nof_symex_objects * sizeof(void *), 1)};
}
void *smap_get(smap_t *smap, void *ptr) {
size_t id = __CPROVER_POINTER_OBJECT(ptr);
void *sptr = smap->ptrs[id];
if (!sptr) {
sptr = __CPROVER_allocate(smap->k * __CPROVER_OBJECT_SIZE(ptr), 1);
smap->ptrs[id] = sptr;
}
return sptr + smap->k * __CPROVER_POINTER_OFFSET(ptr);
}
typedef struct {
uint8_t key;
uint8_t value;
} stk_elem_t;
typedef struct {
int8_t top;
stk_elem_t *elems;
} stk_t;
size_t nondet_size_t();
// Creates a fresh borrow stack
stk_t *stk_new() {
stk_t *stk = __CPROVER_allocate(sizeof(stk_t), 1);
size_t stk_size = nondet_size_t();
__CPROVER_assume(UINT8_MAX <= stk_size && stk_size <= UINT8_MAX);
// works with
// __CPROVER_assume(stk_size == UINT8_MAX);
*stk = (stk_t){
.top = 0,
.elems = __CPROVER_allocate(sizeof(stk_elem_t) * stk_size, 1)};
return stk;
}
void stk_push(stk_t *stk, uint8_t key, uint8_t value) {
assert(stk->top < UINT8_MAX);
stk->elems[stk->top] = (stk_elem_t){.key = key, .value = value};
stk->top++;
}
stk_t *get_stk(smap_t *smap, void *ptr) {
stk_t **stk_ptr = (stk_t **) smap_get(smap, ptr);
if (!(*stk_ptr)) {
*stk_ptr = stk_new();
}
return *stk_ptr;
}
typedef struct {
int a;
int b;
} my_struct_t;
int main() {
smap_t smap;
smap_init(&smap, sizeof(stk_t*));
my_struct_t my_struct;
stk_t *stk_a = get_stk(&smap, &(my_struct.a));
stk_push(stk_a, 1, 1);
stk_t *stk_b = get_stk(&smap, &(my_struct.b));
assert(stk_b);
stk_push(stk_b, 1, 1);
}
CBMC version: 5.79.0 (cbmc-5.79.0-49-gb34e991f30), Z3 version 4.12.1 - 64 bit
Operating system: macOS
Exact command line resulting in the issue:cbmc --pointer-check --smt2 stack_push.c
What behaviour did you expect: analysis suceeds
What happened instead: analysis fails
This program is proved correct with the SAT backend but fails with with SMT2 backend with
--pointer-check --bounds-check:The analysis using the SMT2 backend succeeds if we change the assumption at line 46:
__CPROVER_assume(UINT8_MAX <= stk_size && stk_size <= UINT8_MAX);into
or into an assignment
CBMC version: 5.79.0 (cbmc-5.79.0-49-gb34e991f30), Z3 version 4.12.1 - 64 bit
Operating system: macOS
Exact command line resulting in the issue:
cbmc --pointer-check --smt2 stack_push.cWhat behaviour did you expect: analysis suceeds
What happened instead: analysis fails