Skip to content

Commit d7b38f1

Browse files
committed
Value sets must not return an empty set for nondet symbols
Even when the expression type is not immediately a pointer, some component of the type may be a pointer. As such, it could legitimately appear in pointer dereferencing, and we should at least add "unknown" to the value set. This is a follow-up fix to 3789670: the regression test included yields a spurious counterexample in versions between 3789670 and this bugfix commit. This commit also reverts the (spurious) changes to the double_deref/* regression tests.
1 parent 9b72a5c commit d7b38f1

File tree

5 files changed

+30
-2
lines changed

5 files changed

+30
-2
lines changed

regression/cbmc/double_deref/double_deref_with_pointer_arithmetic.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
double_deref_with_pointer_arithmetic.c
33
--show-vcc
44
^\{-[0-9]+\} derefd_pointer::derefd_pointer!0#1 = \{ symex_dynamic::dynamic_object1#3\[\[0\]\], symex_dynamic::dynamic_object1#3\[\[1\]\] \}\[cast\(mod #source_location=""\(main::argc!0@1#1, 2\), signedbv\[64\]\)\]
5-
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[23]\) \? main::argc!0@1#1 = 2 : main::argc!0@1#1 = 1
5+
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[23]\) \? main::argc!0@1#1 = 2 : \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[23]\) \? main::argc!0@1#1 = 1 : symex::invalid_object!0#0 = main::argc!0@1#1\)\)
66
^EXIT=0$
77
^SIGNAL=0$
88
--

regression/cbmc/double_deref/double_deref_with_pointer_arithmetic_single_alias.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
double_deref_with_pointer_arithmetic_single_alias.c
33
--show-vcc
4-
\{1\} main::argc!0@1#1 = 1
4+
\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object2\) \? main::argc!0@1#1 = 1 : symex::invalid_object!0#0 = main::argc!0@1#1\)
55
^EXIT=0$
66
^SIGNAL=0$
77
--
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <stdlib.h>
2+
3+
struct S
4+
{
5+
int *p;
6+
int x;
7+
};
8+
9+
int main()
10+
{
11+
struct S *s = malloc(sizeof(struct S));
12+
// Guard must not be removed (deemed trivially true) by try_filter_value_sets.
13+
if(s->p != NULL)
14+
__CPROVER_assert(s->p != NULL, "cannot be NULL");
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
nondet.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
try_filter_value_sets must not end up in a situation where it deems the guard
11+
trivially true. This situation arises when the value set wrongly is empty.

src/pointer-analysis/value_set.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ void value_sett::get_value_set_rec(
521521
exprt(ID_null_object, to_pointer_type(expr_type).subtype()),
522522
offsett());
523523
}
524+
else
525+
insert(dest, exprt(ID_unknown, original_type));
524526
}
525527
else if(expr.id()==ID_if)
526528
{

0 commit comments

Comments
 (0)