Skip to content

Spurious pointer check violation with smt2 backend and z3 4.12.1 #7690

@remi-delmas-3000

Description

@remi-delmas-3000

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

stk_size = UINT8_MAX;
#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

Metadata

Metadata

Labels

awsBugs or features of importance to AWS CBMC usersaws-highblockerbug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions