Description
The following program shows the issue but I think it is a lot more general:
$ cat ~/tmp/can-delete/loop.c
#include <assert.h>
int main (void) {
int x;
int i;
if (x > 0) {
for (i = 0; i < x; ++i) {
// Do nothing;
}
} else {
x = 1;
}
assert(x >= 1);
return 0;
}
It looks commit 1218856 works:
$ ./cbmc/cbmc --full-slice --unwind 1 ~/tmp/can-delete/loop.c
CBMC version 5.5 64-bit x86_64 linux
Parsing /home/martin/tmp/can-delete/loop.c
Converting
Type-checking loop
Generating GOTO Program
Adding CPROVER library (x86_64)
Removal of function pointers and virtual functions
Performing a full slice
Partial Inlining
Generic Property Instrumentation
Starting Bounded Model Checking
Not unwinding loop main.0 iteration 1 (1 max) file /home/martin/tmp/can-delete/loop.c line 8 function main thread 0
size of program expression: 26 steps
simple slicing removed 2 assignments
Generated 1 VCC(s), 1 remaining after simplification
Passing problem to propositional reduction
converting SSA
Running propositional reduction
Post-processing
Solving with MiniSAT 2.2.1 with simplifier
199 variables, 464 clauses
SAT checker: instance is UNSATISFIABLE
Runtime decision procedure: 0.003s
** Results:
[main.assertion.1] assertion x >= 1: SUCCESS
** 0 of 1 failed (1 iteration)
VERIFICATION SUCCESSFUL
but the next commit e26d20e doesn't:
$ ./cbmc/cbmc --full-slice --unwind 1 ~/tmp/can-delete/loop.c
CBMC version 5.5 64-bit x86_64 linux
Parsing /home/martin/tmp/can-delete/loop.c
Converting
Type-checking loop
Generating GOTO Program
Adding CPROVER library (x86_64)
Removal of function pointers and virtual functions
Performing a full slice
code
- type: code
- statement: output
- #source_location:
- file: /home/martin/tmp/can-delete/loop.c
- line: 17
- function: main
- working_directory: /home/martin/working-copies/cbmc-git/src
0: address_of- type: pointer
0: signedbv
* width: 8
* #c_type: char
0: index- type: signedbv
- width: 8
- #c_type: char
0: string_constant - type: array
- size: constant
- type: signedbv
- width: 64
- #c_type: signed_long_int
- value: 0000000000000000000000000000000000000000000000000000000000000111
0: signedbv - width: 8
- #c_type: char
- type: signedbv
- size: constant
- value: return
1: constant - type: signedbv
- width: 64
- #c_type: signed_long_int
- value: 0000000000000000000000000000000000000000000000000000000000000000
1: symbol
- type: signedbv
- type: signedbv
- width: 32
- #c_type: signed_int
- identifier: return'
value_set_fit: unexpected statement: output
- type: pointer
The backtrace is interesting because the problem is actually triggered in the value set analysis, despite the changes being to the expression creation:
(gdb) backtrace
#0 0x00007ffff7b2fdbd in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x0000000000425c2e in value_set_fit::apply_code(exprt const&, namespacet const&) ()
#2 0x000000000041baa2 in value_set_domain_fit::transform(namespacet const&, std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont>, std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont>) ()
#3 0x00000000004515b5 in flow_insensitive_analysis_baset::visit(std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont>, std::priority_queue<std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont>, std::vector<std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont>, std::allocator<std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont> > >, std::less<std::_List_const_iterator<goto_program_templatet<codet, exprt>::instructiont> > >&, goto_programt const&, goto_functionst const&) ()
#4 0x00000000004518d3 in flow_insensitive_analysis_baset::fixedpoint(goto_programt const&, goto_functionst const&) ()
#5 0x0000000000452eee in flow_insensitive_analysis_baset::fixedpoint(goto_functionst const&) ()
#6 0x0000000000449643 in reaching_definitions_analysist::initialize(goto_functionst const&) ()
#7 0x0000000000433ff6 in full_slicert::operator()(goto_functionst&, namespacet const&, slicing_criteriont&) ()
#8 0x0000000000434e15 in full_slicer(goto_functionst&, namespacet const&) ()
#9 0x00000000004ac1c8 in cbmc_parse_optionst::process_goto_program(optionst const&, goto_functionst&) ()
#10 0x00000000004ab80f in cbmc_parse_optionst::get_goto_program(optionst const&, bmct&, goto_functionst&) ()
#11 0x00000000004acd8c in cbmc_parse_optionst::doit() ()
#12 0x000000000040bbbd in main ()
which makes me concerned that the value set analysis might not be the only bit of code that makes these assumptions about expressions that are broken by this change.
@lucasccordeiro : person who said they'd work on it
@peterschrammel : person who wrote the original patch
@kroening : person who merged this