Skip to content

A question on pointer operations with CBMC #1252

@fangyi-zhou

Description

@fangyi-zhou

I have the question when I play around uintptr_t with CBMC

#include <stdio.h>
#include <stdint.h>

int main() {
    int x;
    int * ptr = &x;
    *ptr = 42;
    uintptr_t uptr = (uintptr_t) ptr;
    uptr = ~uptr;
    uptr = ~uptr;
    int * ptr2 = (int *) uptr;
    __CPROVER_assert(ptr == ptr2, "pointer is identical");
    printf("*ptr = %d, *ptr2 = %d\n", *ptr, *ptr2);
    __CPROVER_assert(*ptr == *ptr2, "pointer dereferenced is identical");
}

Result by CBMC:

CBMC version 5.8 64-bit x86_64 macos
Parsing ptr.c
Converting
Type-checking ptr
Generating GOTO Program
Adding CPROVER library (x86_64)
Removal of function pointers and virtual functions
Partial Inlining
Generic Property Instrumentation
Starting Bounded Model Checking
size of program expression: 46 steps
simple slicing removed 5 assignments
Generated 2 VCC(s), 2 remaining after simplification
Passing problem to propositional reduction
converting SSA
Running propositional reduction
Post-processing
Solving with MiniSAT 2.2.1 with simplifier
330 variables, 205 clauses
SAT checker: instance is SATISFIABLE
Solving with MiniSAT 2.2.1 with simplifier
330 variables, 0 clauses
SAT checker inconsistent: instance is UNSATISFIABLE
Runtime decision procedure: 0.002s

** Results:
[main.assertion.1] pointer is identical: SUCCESS
[main.assertion.2] pointer dereferenced is identical: FAILURE

** 1 of 2 failed (2 iterations)
VERIFICATION FAILED

It is interesting why the pointers are identical, but the dereferenced pointers are not. With a trace, I made the following discovery:

State 20 file ptr.c line 6 function main thread 0
----------------------------------------------------
  ptr=&x!0@1 (0000001000000000000000000000000000000000000000000000000000000000)

(omitted)

State 27 file ptr.c line 11 function main thread 0
----------------------------------------------------
  ptr2=&x!0@1 (0000001000000000000000000000000000000000000000000000000000000000)
*ptr = 42, *ptr2 = 16384

For some reason, *ptr is 16384.

While I'm not entirely sure whether my code is triggering any undefined behaviour because C standard only guarantees that uintptr_t can be used for casting from and to void*, without specifying any operations permitted on the data type. The result of CBMC is cryptic and difficult to understand.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions