Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option --full-slice is unsound #260

Open
peterschrammel opened this issue Oct 19, 2016 · 18 comments
Open

Option --full-slice is unsound #260

peterschrammel opened this issue Oct 19, 2016 · 18 comments

Comments

@peterschrammel
Copy link
Member

add regression tests for C

@kroening, any observations what goes wrong with --full-slice at the moment?

@lucasccordeiro
Copy link
Contributor

@kroening: can you also provide some starting point for this particular task? For example, which test cases should I consider (or if I have to create a test suite)? What is actually wrong with --full-slice and --all-properties? Which additional options should I use to test --full-slice and --all-properties (e.g., cbmc file.c --full-slice, cbmc file.c --all-properties)?

@lucasccordeiro
Copy link
Contributor

@peterschrammel: which test suite can I add regression tests related to this issue? It seems that the --all-properties option is related to cbmc-incr. Is that correct? However, --full-slice option is not clear which test suite I can add test cases to.

@lucasccordeiro
Copy link
Contributor

Just to keep the history.

@tautschnig: This is the example with pointers that I mentioned in your visit at DiffBlue.

void *malloc(__CPROVER_size_t);
void free(void *);
int main()
{
  int *p=malloc(sizeof(int));
  int *q=p;
  int i, x;
  i=x;
  if(i==4711) free(q);
  // should fail if i==4711
  *p=1;
}

I was getting a different verification result when verifying it with --full-slice.

Additionally, the full-slice option gives incorrect results for the following C programs from cbmc regression suite:

Running Fixedbv3/test.desc [FAILED]
Running Float3/test.desc [FAILED]
Running Float3/test.desc [FAILED]
Running Function5/test.desc [FAILED]
Running Function6/test.desc [FAILED]
Running Local_out_of_scope1/test.desc [FAILED]
Running Memory_leak1/test.desc [FAILED]
Running Overflow_Addition1/test.desc [FAILED]
Running Pointer_Arithmetic5/test.desc [FAILED]
Running Pointer_byte_extract5/test.desc [FAILED]
Running Sideeffects5/test.desc [FAILED]
Running Sideeffects6/test.desc [FAILED]
Running String2/test.desc [FAILED]
Running String6/test.desc [FAILED]
Running Undefined_Function1/test.desc [FAILED]
Running Undefined_Function2/test.desc [FAILED]
Running array-tests/test.desc [FAILED]
Running complex1/test.desc [FAILED]
Running equality_through_union3/test.desc [FAILED]
Running exit1/test.desc [FAILED]
Running gcc_vector2/test.descbash: line 1: 21193 Aborted (core dumped) ../../../src/cbmc/cbmc --full-slice main.c > main.out 2>&1
[FAILED]
Running realloc1/test.desc [FAILED]
Running realloc2/test.desc [FAILED]
Running realloc3/test.desc [FAILED]
Running struct6/test.desc [FAILED]

We believe that issue #327 should resolve part of these problems.

@lucasccordeiro
Copy link
Contributor

lucasccordeiro commented Dec 14, 2016

We have made some progress with the full-slice option, but we are still facing issues about the functional call. Here is the current status of the CBMC regression suite when using the --full-slice option:

Fixedbv3/test.desc  [FAILED]
Float3/test.desc  [FAILED]
Function6/test.desc  [FAILED]
array-tests/test.desc  [FAILED]
equality_through_union3/test.desc  [FAILED]
realloc1/test.desc  [FAILED]
realloc2/test.desc  [FAILED]
realloc3/test.desc  [FAILED]

@lucasccordeiro
Copy link
Contributor

@tautschnig: After integrating your work from #327 into my branch, most benchmarks fail due to "failed to find state". In particular, this part of the code in the ai.h:

  inline const domainT &operator[](locationt l) const
  {
    typename state_mapt::const_iterator it=state_map.find(l);
    if(it==state_map.end()) throw "failed to find state";
    return it->second;
  }

It must be some minor issue to solve, but I'm still unable to find the root cause. Do you have any suggestion?

@lucasccordeiro
Copy link
Contributor

Some additional information about the debug process. It seems that we correctly build the CFG, fill the queue according to slicing criterion, and then compute the program dependence graph (and post-dominators). However, when we try computing the fixedpoint, we simply get "failed to find state" after adding the data / control dependencies for a given node.

@lucasccordeiro
Copy link
Contributor

lucasccordeiro commented Dec 14, 2016

If we check whether a given state exists before we add data / control dependencies, then apparently it solves the problem; however, I'm unsure whether this fix is correct. This really needs further investigation. Here is the current status if I run CBMC regression suite using the full-slice option:

Memmove1/test.desc  [FAILED]
Recursion3/test.desc  [FAILED]
Recursion4/test.desc  [FAILED]
Recursion6/test.desc  [FAILED]
array-tests/test.desc  [FAILED]
equality_through_union3/test.desc  [FAILED]
realloc1/test.desc  [FAILED]
realloc2/test.desc  [FAILED]

@tautschnig
Copy link
Collaborator

Thanks lot for all the updates! Unfortunately I won't find time to properly look into this before Saturday, but any notes posted by then will be of help.

@lucasccordeiro
Copy link
Contributor

@tautschnig: I was just wondering whether you had a chance to look at this issue? I'm going to create some issue in github so that I can get assistance to fix further bugs that I have found in the dependence graph (e.g., C programs with unions are not fully supported).

@lucasccordeiro
Copy link
Contributor

@tautschnig: If we check for array_copy during the implicit call in the full slicer, then we can fix the issues related to the test cases realloc1 and realloc2.

static bool implicit(const namespacet &ns, goto_programt::const_targett target)
{
  // some variables are used during symbolic execution only

  const irep_idt &statement=target->code.get(ID_statement);
  if (statement==ID_array_copy) return true;
  ...
}

However, we still have 6 issues to fix in the CBMC regression suite as follows:

Memmove1/test.desc  [FAILED]
Recursion3/test.desc  [FAILED]
Recursion4/test.desc  [FAILED]
Recursion6/test.desc  [FAILED]
array-tests/test.desc  [FAILED]
equality_through_union3/test.desc  [FAILED]

I have open a ticket in github to further investigate the test case equality_through_union3 (#380).

I'll take a look at the other test cases that are failing.

@lucasccordeiro
Copy link
Contributor

@kroening and @tautschnig: I have updated my branch with the latest version of the CBMC master branch. This particular commit starts breaking the full-slice option of CBMC:

fca6cd6 (make_top, make_bottom, make_entry are now are required)

In order to reproduce the problem, you can just compile and run the CBMC master branch as follows:

lucascordeiro@lucascordeiro:~/cbmc/regression/cbmc/equality_through_array1$ ~/cbmc/src/cbmc/cbmc main.c --full-slice
CBMC version 5.6 64-bit x86_64 linux
Parsing main.c
file <command-line> line 0: <command-line>:0:0: warning: "__STDC_VERSION__" redefined
<built-in>: note: this is the location of the previous definition
Converting
Type-checking main
file main.c line 17 function main: function `assert' is not declared
file main.c line 19 function main: function has return void but a return statement returning signed int
Generating GOTO Program
Adding CPROVER library (x86_64)
Removal of function pointers and virtual functions
Performing a full slice
cbmc: ../analyses/dependence_graph.h:124: dep_graph_domaint::node_indext dep_graph_domaint::get_node_id() const: Assertion `node_id!=std::numeric_limits<node_indext>::max()' failed.
Aborted (core dumped)

I'm struggling for some days to find a solution for this particular problem as I don't understand very well this AI code. In the full slicer code, I'm unsure whether I'm incorrectly instantiating the program dependence graph after all those changes to the CBMC master:

  // compute program dependence graph (and post-dominators)
  dependence_grapht dep_graph(ns);
  dep_graph(goto_functions, ns);

I've also talked to @danpoe to get some help on the AI code, but this particular part of the code (i.e., the dependence graph) is also new for him.

I would appreciate any support from @kroening and @tautschnig since I have no idea about the root cause of the problem.

@danpoe
Copy link
Contributor

danpoe commented Jan 10, 2017

I think I know what the problem is. get_state() is overridden to set the node id but initialize() then sets it to unsigned_max() again. I'll provide a fix.

@lucasccordeiro
Copy link
Contributor

I have integrated the fix from #420 into my branch https://github.com/lucasccordeiro/cbmc/tree/dependence-graph-fix and also fixed more 3 test cases.

The current results of running the full-slice option over the CBMC regression suite is:

Memmove1/test.desc  [FAILED]
Recursion6/test.desc  [FAILED]
equality_through_union3/test.desc  [FAILED]

@forejtv forejtv added this to the Java Sprint 1 milestone Feb 7, 2017
smowton pushed a commit to smowton/cbmc that referenced this issue May 9, 2018
SEC-105 Cleanup LVSA code (nothing functional)
chrisr-diffblue added a commit to chrisr-diffblue/cbmc that referenced this issue Aug 24, 2018
…in-methods-for-vs-dependence-graph

Specialised AI domain methods for variable sensitivity dependence graph
@peterschrammel peterschrammel changed the title Test and repair --full-slice and --all-properties Option --full-slice is broken Feb 20, 2021
@peterschrammel peterschrammel changed the title Option --full-slice is broken Option --full-slice is unsound Feb 21, 2021
@NlightNFotis
Copy link
Contributor

An update on this:

Tracing the tests here is hard (because some of them have been deleted in subsequent PRs, and others are running as part of our CORE regression suite run).

However, the --full-slice options appears to be working most of the time.

There exist some cases however (when you change the CMakeLists.txt under regression/cbmc as an example) where we do get flipped verification results. The reason for this appears to be that the function body of a function assigning to a variable that later gets asserted on appears to be sliced out, causing verification to flip from successful to failed.

An example of that would be the test regression/CBMC/Bool5, which as of now contains the following in test.desc:

CORE
main.c

Generated 4 VCC\(s\), 0 remaining after simplification
^VERIFICATION SUCCESSFUL$
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring

with the execution log being this:

CBMC version 5.52.0 (cbmc-5.52.0-6-g3c16b8dcd-dirty) 64-bit arm64 macos
Parsing main.c
Converting
Type-checking main
Generating GOTO Program
Adding CPROVER library (arm64)
Removal of function pointers and virtual functions
Generic Property Instrumentation
WARNING: Unsound option --full-slice
Performing a full slice
Running with 8 object bits, 56 offset bits (default)
Starting Bounded Model Checking
Runtime Symex: 0.000503042s
size of program expression: 27 steps
simple slicing removed 3 assignments
Generated 4 VCC(s), 1 remaining after simplification
Runtime Postprocess Equation: 1.5625e-05s
Passing problem to propositional reduction
converting SSA
Runtime Convert SSA: 0.000187959s
Running propositional reduction
Post-processing
Runtime Post-process: 8.042e-06s
Solving with MiniSAT 2.2.1 with simplifier
331 variables, 174 clauses
SAT checker: instance is SATISFIABLE
Runtime Solver: 6.9417e-05s
Runtime decision procedure: 0.000275292s

** Results:
main.c function main
[main.precondition_instance.1] line 14 memcpy src/dst overlap: SUCCESS
[main.precondition_instance.2] line 14 memcpy source region readable: SUCCESS
[main.precondition_instance.3] line 14 memcpy destination region writeable: SUCCESS
[main.assertion.1] line 16 assertion num == 1: FAILURE

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

EXIT=10
SIGNAL=0

Notice the last assertion, which is the only assertion present in the code (assert(num == 1); in main.c).

If we ask for a trace for that we get:

[main.assertion.1] line 16 assertion num == 1: FAILURE

Trace for main.assertion.1:

State 8 file main.c function main line 12 thread 0
----------------------------------------------------
  conf_init={ .red=conf_init!0@1#1..red, .$pad1=conf_init!0@1#1..$pad1, .one=conf_init!0@1#1..one } ({ ?, ?, ? })

State 9 file main.c function main line 13 thread 0
----------------------------------------------------
  my_conf={ .red=my_conf!0@1#1..red, .$pad1=my_conf!0@1#1..$pad1, .one=128 } ({ ?, ?, 00000000 00000000 00000000 10000000 })

State 12 file main.c function main line 14 thread 0
----------------------------------------------------
  dst=(const void *)&[email protected] (?)

State 13 file main.c function main line 14 thread 0
----------------------------------------------------
  src=(const void *)&[email protected] (?)

State 14 file main.c function main line 14 thread 0
----------------------------------------------------
  n=sizeof(struct conft) /*8ul*/  (00000000 00000000 00000000 00000000 00000000 00000000 00000000 00001000)

State 15 file main.c function main line 14 thread 0
----------------------------------------------------
  size=18446744073709551615ul (11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111)

State 19 file main.c function main line 15 thread 0
----------------------------------------------------
  num=0 (00000000 00000000 00000000 00000000)

State 20 file main.c function main line 15 thread 0
----------------------------------------------------
  num=128 (00000000 00000000 00000000 10000000)

Violated property:
  file main.c function main line 16 thread 0
  assertion num == 1
  !((signed long int)(signed long int)!(num == 1) != 0l)



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

If we ask to see the goto-functions before and after the slice, we get the following:

BEFORE:

CBMC version 5.52.0 (cbmc-5.52.0-6-g3c16b8dcd-dirty) 64-bit arm64 macos
Parsing ../regression/cbmc/Bool5/main.c
Converting
Type-checking main
Generating GOTO Program
Adding CPROVER library (arm64)
Removal of function pointers and virtual functions
Generic Property Instrumentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__CPROVER__start /* __CPROVER__start */
        // 45 no location
        // Labels: __CPROVER_HIDE
        CALL __CPROVER_initialize()
        // 46 file ../regression/cbmc/Bool5/main.c line 10
        CALL return' := main()
        // 47 file ../regression/cbmc/Bool5/main.c line 10
        OTHER code #source_location="" statement="output"(address_of("return'"[0]), return')
        // 48 no location
        END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__CPROVER_initialize /* __CPROVER_initialize */
        // 15 file <built-in-additions> line 19
        // Labels: __CPROVER_HIDE
        ASSIGN __CPROVER_alloca_object := NULL
        // 16 file <built-in-additions> line 14
        ASSIGN __CPROVER_dead_object := NULL
        // 17 file <built-in-additions> line 13
        ASSIGN __CPROVER_deallocated := NULL
        // 18 file <built-in-additions> line 16
        ASSIGN __CPROVER_malloc_is_new_array := 0 ≠ 0
        // 19 file <built-in-additions> line 20
        ASSIGN __CPROVER_max_malloc_size := cast(36028797018963968, unsignedbv[64])
        // 20 file <built-in-additions> line 17
        ASSIGN __CPROVER_memory_leak := NULL
        // 21 file <built-in-additions> line 15
        ASSIGN __CPROVER_new_object := NULL
        // 22 file <built-in-additions> line 8
        ASSIGN __CPROVER_next_thread_id := cast(0, unsignedbv[64])
        // 23 file <built-in-additions> line 11
        ASSIGN __CPROVER_next_thread_key := cast(0, unsignedbv[64])
        // 24 file <built-in-additions> line 33
        ASSIGN __CPROVER_pipe_count := cast(0, unsignedbv[32])
        // 25 file <built-in-additions> line 24
        ASSIGN __CPROVER_rounding_mode := 0
        // 26 file <built-in-additions> line 6
        ASSIGN __CPROVER_thread_id := cast(0, unsignedbv[64])
        // 27 file <built-in-additions> line 10
        ASSIGN __CPROVER_thread_key_dtors := array_of #source_location=""(NULL)
        // 28 file <built-in-additions> line 9
        ASSIGN __CPROVER_thread_keys := array_of #source_location=""(NULL)
        // 29 file <built-in-additions> line 7
        ASSIGN __CPROVER_threads_exited := array_of #source_location=""(false)
        // 30 no location
        END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__builtin___memcpy_chk /* __builtin___memcpy_chk */
        // 31 file <builtin-library-__builtin___memcpy_chk> line 25 function __builtin___memcpy_chk
        LOCATION
        // 32 file <builtin-library-__builtin___memcpy_chk> line 30 function __builtin___memcpy_chk
        LOCATION
        // 33 file <builtin-library-__builtin___memcpy_chk> line 32 function __builtin___memcpy_chk
        LOCATION
        // 34 file <builtin-library-__builtin___memcpy_chk> line 34 function __builtin___memcpy_chk
        OTHER code #source_location="" statement="expression"(cast(__builtin___memcpy_chk::size, empty))
        // 35 file <builtin-library-__builtin___memcpy_chk> line 36 function __builtin___memcpy_chk
        IF ¬(__builtin___memcpy_chk::n > cast(0, unsignedbv[64])) THEN GOTO 1
        // 36 file <builtin-library-__builtin___memcpy_chk> line 39 function __builtin___memcpy_chk
        DECL __builtin___memcpy_chk::1::1::src_n$array_size::src_n$array_size : unsignedbv[64]
        // 37 file <builtin-library-__builtin___memcpy_chk> line 39 function __builtin___memcpy_chk
        ASSIGN __builtin___memcpy_chk::1::1::src_n$array_size::src_n$array_size := cast(cast(__builtin___memcpy_chk::n, signedbv[64]), unsignedbv[64])
        // 38 file <builtin-library-__builtin___memcpy_chk> line 39 function __builtin___memcpy_chk
        DECL __builtin___memcpy_chk::1::1::src_n : signedbv[8][__builtin___memcpy_chk::1::1::src_n$array_size::src_n$array_size]
        // 39 file <builtin-library-__builtin___memcpy_chk> line 40 function __builtin___memcpy_chk
        OTHER code #source_location="" statement="array_copy"(cast(address_of(__builtin___memcpy_chk::1::1::src_n[0]), empty*), cast(cast(__builtin___memcpy_chk::src, signedbv[8]*), empty*))
        // 40 file <builtin-library-__builtin___memcpy_chk> line 41 function __builtin___memcpy_chk
        OTHER code #source_location="" statement="array_replace"(cast(cast(__builtin___memcpy_chk::dst, signedbv[8]*), empty*), cast(address_of(__builtin___memcpy_chk::1::1::src_n[0]), empty*))
        // 41 file <builtin-library-__builtin___memcpy_chk> line 42 function __builtin___memcpy_chk
        DEAD __builtin___memcpy_chk::1::1::src_n
        // 42 file <builtin-library-__builtin___memcpy_chk> line 42 function __builtin___memcpy_chk
        DEAD __builtin___memcpy_chk::1::1::src_n$array_size::src_n$array_size
        // 43 file <builtin-library-__builtin___memcpy_chk> line 44 function __builtin___memcpy_chk
     1: SET RETURN VALUE __builtin___memcpy_chk::dst
        // 44 file <builtin-library-__builtin___memcpy_chk> line 45 function __builtin___memcpy_chk
        END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

main /* main */
        // 0 file ../regression/cbmc/Bool5/main.c line 12 function main
        DECL main::1::conf_init : struct tag-conft
        // 1 file ../regression/cbmc/Bool5/main.c line 12 function main
        ASSIGN main::1::conf_init := { cast(0, c_bool[8]), 0, 1 }
        // 2 file ../regression/cbmc/Bool5/main.c line 13 function main
        DECL main::1::my_conf : struct tag-conft
        // 3 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT (pointer_object #source_location=""(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*)) ≠ pointer_object #source_location=""(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*)) ∨ cast(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), signedbv[8]*) ≥ cast(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), signedbv[8]*) + cast(8, signedbv[64])) ∨ cast(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), signedbv[8]*) ≥ cast(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), signedbv[8]*) + cast(8, signedbv[64]) // memcpy src/dst overlap
        // 4 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT ¬(pointer_object(address_of #source_location=""(main::1::conf_init)) = pointer_object(__CPROVER_dead_object)) // memcpy source region readable
        // 5 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT ¬(pointer_object(address_of #source_location=""(main::1::my_conf)) = pointer_object(__CPROVER_dead_object)) // memcpy destination region writeable
        // 6 file ../regression/cbmc/Bool5/main.c line 14 function main
        CALL __builtin___memcpy_chk(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), 8, 18446744073709551615)
        // 7 file ../regression/cbmc/Bool5/main.c line 15 function main
        DECL main::1::num : signedbv[32]
        // 8 file ../regression/cbmc/Bool5/main.c line 15 function main
        ASSIGN main::1::num := main::1::my_conf.one
        // 9 file ../regression/cbmc/Bool5/main.c line 16 function main
        ASSERT ¬(cast(cast(¬(main::1::num = 1), signedbv[64]), signedbv[64]) ≠ 0) // assertion num == 1
        // 10 file ../regression/cbmc/Bool5/main.c line 17 function main
        SET RETURN VALUE 0
        // 11 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::num
        // 12 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::my_conf
        // 13 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::conf_init
        // 14 file ../regression/cbmc/Bool5/main.c line 18 function main
        END_FUNCTION

AFTER:

CBMC version 5.52.0 (cbmc-5.52.0-6-g3c16b8dcd-dirty) 64-bit arm64 macos
Parsing ../regression/cbmc/Bool5/main.c
Converting
Type-checking main
Generating GOTO Program
Adding CPROVER library (arm64)
Removal of function pointers and virtual functions
Generic Property Instrumentation
WARNING: Unsound option --full-slice
Performing a full slice
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__CPROVER__start /* __CPROVER__start */
        // 19 no location
        // Labels: __CPROVER_HIDE
        CALL __CPROVER_initialize()
        // 20 file ../regression/cbmc/Bool5/main.c line 10
        CALL return' := main()
        // 21 no location
        END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__CPROVER_initialize /* __CPROVER_initialize */
        // 13 file <built-in-additions> line 14
        // Labels: __CPROVER_HIDE
        ASSIGN __CPROVER_dead_object := NULL
        // 14 file <built-in-additions> line 24
        ASSIGN __CPROVER_rounding_mode := 0
        // 15 no location
        END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

__builtin___memcpy_chk /* __builtin___memcpy_chk */
        // 16 file <builtin-library-__builtin___memcpy_chk> line 36 function __builtin___memcpy_chk
        IF ¬(__builtin___memcpy_chk::n > cast(0, unsignedbv[64])) THEN GOTO 1
        // 17 file <builtin-library-__builtin___memcpy_chk> line 40 function __builtin___memcpy_chk
        OTHER code #source_location="" statement="array_copy"(cast(address_of(__builtin___memcpy_chk::1::1::src_n[0]), empty*), cast(cast(__builtin___memcpy_chk::src, signedbv[8]*), empty*))
        // 18 file <builtin-library-__builtin___memcpy_chk> line 45 function __builtin___memcpy_chk
     1: END_FUNCTION

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

main /* main */
        // 0 file ../regression/cbmc/Bool5/main.c line 12 function main
        DECL main::1::conf_init : struct tag-conft
        // 1 file ../regression/cbmc/Bool5/main.c line 13 function main
        DECL main::1::my_conf : struct tag-conft
        // 2 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT (pointer_object #source_location=""(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*)) ≠ pointer_object #source_location=""(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*)) ∨ cast(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), signedbv[8]*) ≥ cast(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), signedbv[8]*) + cast(8, signedbv[64])) ∨ cast(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), signedbv[8]*) ≥ cast(cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), signedbv[8]*) + cast(8, signedbv[64]) // memcpy src/dst overlap
        // 3 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT ¬(pointer_object(address_of #source_location=""(main::1::conf_init)) = pointer_object(__CPROVER_dead_object)) // memcpy source region readable
        // 4 file ../regression/cbmc/Bool5/main.c line 14 function main
        ASSERT ¬(pointer_object(address_of #source_location=""(main::1::my_conf)) = pointer_object(__CPROVER_dead_object)) // memcpy destination region writeable
        // 5 file ../regression/cbmc/Bool5/main.c line 14 function main
        CALL __builtin___memcpy_chk(cast(cast(address_of #source_location=""(main::1::my_conf), signedbv[8]*), empty*), cast(cast(address_of #source_location=""(main::1::conf_init), signedbv[8]*), empty*), 8, 18446744073709551615)
        // 6 file ../regression/cbmc/Bool5/main.c line 15 function main
        DECL main::1::num : signedbv[32]
        // 7 file ../regression/cbmc/Bool5/main.c line 15 function main
        ASSIGN main::1::num := main::1::my_conf.one
        // 8 file ../regression/cbmc/Bool5/main.c line 16 function main
        ASSERT ¬(cast(cast(¬(main::1::num = 1), signedbv[64]), signedbv[64]) ≠ 0) // assertion num == 1
        // 9 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::num
        // 10 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::my_conf
        // 11 file ../regression/cbmc/Bool5/main.c line 17 function main
        DEAD main::1::conf_init
        // 12 file ../regression/cbmc/Bool5/main.c line 18 function main
        END_FUNCTION

As you can notice, --full-slice ended up purging most of the bodies of the other functions, including memcpy which is on the main path. By eliminating the body of memcpy in this case, we are losing the assignment inside the function, resulting in memcpy not having its semantics represented properly, so we lose track of the values from that point onwards.

@tautschnig
Copy link
Collaborator

@NlightNFotis thank you so much for digging deeper here! It won't be the last problem that needs fixing, but on this occasion it seems that the lack of handling array_copy and array_replace semantics is the culprit. I'm working on a fix, and might ask for more help in diagnosing errors if that's ok?

@tautschnig tautschnig self-assigned this Mar 7, 2022
@NlightNFotis
Copy link
Contributor

@tautschnig Not a problem at all. Anything I can do, just let me know - happy to help with getting to the bottom of this.

@tautschnig
Copy link
Collaborator

So I'll now wait for #6710 and #6711 to be merged before looking into what is left to be done. Just enabling --full-slice for all tests was a great idea!

tautschnig added a commit to tautschnig/cbmc that referenced this issue Apr 12, 2022
To ensure --full-slice keeps working on all of CBMC's regression tests,
run them in CI via an additional test profile. Some tests have to be
excluded for they rely on program statements not being removed.

Fixes: diffblue#260
tautschnig added a commit to tautschnig/cbmc that referenced this issue Apr 22, 2022
To ensure --full-slice keeps working on all of CBMC's regression tests,
run them in CI via an additional test profile. Some tests have to be
excluded for they rely on program statements not being removed.

Fixes: diffblue#260
ronakfof pushed a commit to ronakfof/cbmc that referenced this issue Apr 22, 2022
To ensure --full-slice keeps working on all of CBMC's regression tests,
run them in CI via an additional test profile. Some tests have to be
excluded for they rely on program statements not being removed.

Fixes: diffblue#260
@tautschnig
Copy link
Collaborator

It won't be the last bug to resolve, but this is currently blocked by a bug in how we handle recursion in the abstract interpreter, see also #7041 (comment).

@tautschnig tautschnig assigned martin-cs and unassigned tautschnig Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants