File tree Expand file tree Collapse file tree 6 files changed +92
-6
lines changed
Expand file tree Collapse file tree 6 files changed +92
-6
lines changed Original file line number Diff line number Diff line change 33int main ()
44{
55 unsigned int * s_pdt = (unsigned int * )(0xdeadbeef );
6- assert (s_pdt > 1 );
6+ // this is well defined
7+ assert ((unsigned long long )s_pdt > 1 );
8+ // this is undefined as it could both be a comparison over integers as well as
9+ // over pointers; the latter may mean comparing pointers to different objects,
10+ // so guard against that
11+ assert (
12+ __CPROVER_POINTER_OBJECT (s_pdt ) !=
13+ __CPROVER_POINTER_OBJECT ((unsigned int * )1 ) ||
14+ s_pdt > 1 );
715 return 0 ;
816}
Original file line number Diff line number Diff line change 11#include <assert.h>
22#include <stdlib.h>
33
4+ char * nondet_pointer ();
5+
46int main ()
57{
68 int * p1 = malloc (sizeof (int ));
79
810 assert (p1 < p1 + 1 );
11+
12+ int * p2 = malloc (sizeof (int ));
13+
14+ assert (p1 != p2 );
15+
16+ _Bool nondet ;
17+ // In the current implementation, CBMC always produces "false" for a
18+ // comparison over different objects. This could change at any time, which
19+ // would require updating this test.
20+ if (nondet )
21+ __CPROVER_assert (p1 < p2 , "always false for different objects" );
22+ else
23+ __CPROVER_assert (p1 > p2 , "always false for different objects" );
24+
25+ char * p = nondet_pointer ();
26+
27+ __CPROVER_assume (p < p1 + 1 );
28+ assert (__CPROVER_POINTER_OBJECT (p ) == __CPROVER_POINTER_OBJECT (p1 ));
929}
Original file line number Diff line number Diff line change 11CORE
22main.c
33
4- ^VERIFICATION SUCCESSFUL$
5- ^EXIT=0$
4+ ^\[main.assertion.3\] line 21 always false for different objects: FAILURE$
5+ ^\[main.assertion.4\] line 23 always false for different objects: FAILURE$
6+ ^\*\* 2 of 7 failed
7+ ^VERIFICATION FAILED$
8+ ^EXIT=10$
69^SIGNAL=0$
710--
811^warning: ignoring
Original file line number Diff line number Diff line change @@ -172,8 +172,30 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
172172 const bvt &bv0=convert_bv (operands[0 ]);
173173 const bvt &bv1=convert_bv (operands[1 ]);
174174
175- return bv_utils.rel (
176- bv0, expr.id (), bv1, bv_utilst::representationt::UNSIGNED);
175+ const pointer_typet &type0 = to_pointer_type (operands[0 ].type ());
176+ bvt offset_bv0 = offset_literals (bv0, type0);
177+
178+ const pointer_typet &type1 = to_pointer_type (operands[1 ].type ());
179+ bvt offset_bv1 = offset_literals (bv1, type1);
180+
181+ // Comparison over pointers to distinct objects is undefined behavior in
182+ // C; we choose to always produce "false" in such a case. Alternatively,
183+ // we could do a comparison over the integer representation of a pointer
184+
185+ // do the same-object-test via an expression as this may permit re-using
186+ // already cached encodings of the equality test
187+ const exprt same_object = ::same_object (operands[0 ], operands[1 ]);
188+ const literalt same_object_lit = convert (same_object);
189+ if (same_object_lit.is_false ())
190+ return same_object_lit;
191+
192+ return prop.land (
193+ same_object_lit,
194+ bv_utils.rel (
195+ offset_bv0,
196+ expr.id (),
197+ offset_bv1,
198+ bv_utilst::representationt::SIGNED));
177199 }
178200 }
179201
Original file line number Diff line number Diff line change @@ -27,6 +27,7 @@ Author: Daniel Kroening, kroening@kroening.com
2727#include < util/namespace.h>
2828#include < util/pointer_expr.h>
2929#include < util/pointer_offset_size.h>
30+ #include < util/pointer_predicates.h>
3031#include < util/prefix.h>
3132#include < util/range.h>
3233#include < util/simplify_expr.h>
@@ -3165,7 +3166,6 @@ void smt2_convt::convert_relation(const binary_relation_exprt &expr)
31653166 const typet &op_type=expr.op0 ().type ();
31663167
31673168 if (op_type.id ()==ID_unsignedbv ||
3168- op_type.id ()==ID_pointer ||
31693169 op_type.id ()==ID_bv)
31703170 {
31713171 out << " (" ;
@@ -3238,6 +3238,31 @@ void smt2_convt::convert_relation(const binary_relation_exprt &expr)
32383238 convert_expr (expr.op1 ());
32393239 out << " )" ;
32403240 }
3241+ else if (op_type.id () == ID_pointer)
3242+ {
3243+ const exprt same_object = ::same_object (expr.op0 (), expr.op1 ());
3244+
3245+ out << " (and " ;
3246+ convert_expr (same_object);
3247+
3248+ out << " (" ;
3249+ if (expr.id () == ID_le)
3250+ out << " bvsle" ;
3251+ else if (expr.id () == ID_lt)
3252+ out << " bvslt" ;
3253+ else if (expr.id () == ID_ge)
3254+ out << " bvsge" ;
3255+ else if (expr.id () == ID_gt)
3256+ out << " bvsgt" ;
3257+
3258+ out << ' ' ;
3259+ convert_expr (pointer_offset (expr.op0 ()));
3260+ out << ' ' ;
3261+ convert_expr (pointer_offset (expr.op1 ()));
3262+ out << ' )' ;
3263+
3264+ out << ' )' ;
3265+ }
32413266 else
32423267 UNEXPECTEDCASE (
32433268 " unsupported type for " +expr.id_string ()+" : " +op_type.id_string ());
Original file line number Diff line number Diff line change @@ -1473,6 +1473,14 @@ simplify_exprt::resultt<> simplify_exprt::simplify_inequality_no_constant(
14731473 if (expr.op0 ().type ().id () == ID_floatbv)
14741474 return unchanged (expr);
14751475
1476+ // simplifications below require same-object, which we don't check for
1477+ if (
1478+ expr.op0 ().type ().id () == ID_pointer && expr.id () != ID_equal &&
1479+ expr.id () != ID_notequal)
1480+ {
1481+ return unchanged (expr);
1482+ }
1483+
14761484 // eliminate strict inequalities
14771485 if (expr.id ()==ID_notequal)
14781486 {
You can’t perform that action at this time.
0 commit comments