Skip to content

Commit 7e0641f

Browse files
author
Daniel Kroening
committed
refactor pointer_validity_check using address_check
1 parent b176bd0 commit 7e0641f

File tree

1 file changed

+41
-181
lines changed

1 file changed

+41
-181
lines changed

src/analyses/goto_check.cpp

Lines changed: 41 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,21 @@ class goto_checkt
9999

100100
using conditionst = std::list<conditiont>;
101101

102-
void bounds_check(const index_exprt &expr, const guardt &guard);
103-
void div_by_zero_check(const div_exprt &expr, const guardt &guard);
104-
void mod_by_zero_check(const mod_exprt &expr, const guardt &guard);
105-
void undefined_shift_check(const shift_exprt &expr, const guardt &guard);
106-
void pointer_rel_check(const exprt &expr, const guardt &guard);
107-
void pointer_overflow_check(const exprt &expr, const guardt &guard);
108-
void pointer_validity_check(
109-
const dereference_exprt &expr,
110-
const guardt &guard,
111-
const exprt &access_lb,
112-
const exprt &access_ub);
102+
void bounds_check(const index_exprt &, const guardt &);
103+
void div_by_zero_check(const div_exprt &, const guardt &);
104+
void mod_by_zero_check(const mod_exprt &, const guardt &);
105+
void undefined_shift_check(const shift_exprt &, const guardt &);
106+
void pointer_rel_check(const exprt &, const guardt &);
107+
void pointer_overflow_check(const exprt &, const guardt &);
108+
void pointer_validity_check(const dereference_exprt &, const guardt &);
113109
conditionst address_check(const exprt &address, const exprt &size);
114-
void integer_overflow_check(const exprt &expr, const guardt &guard);
115-
void conversion_check(const exprt &expr, const guardt &guard);
116-
void float_overflow_check(const exprt &expr, const guardt &guard);
117-
void nan_check(const exprt &expr, const guardt &guard);
118-
void rw_ok_check(exprt &expr);
110+
void integer_overflow_check(const exprt &, const guardt &);
111+
void conversion_check(const exprt &, const guardt &);
112+
void float_overflow_check(const exprt &, const guardt &);
113+
void nan_check(const exprt &, const guardt &);
114+
void rw_ok_check(exprt &);
119115

120-
std::string array_name(const exprt &expr);
116+
std::string array_name(const exprt &);
121117

122118
void add_guarded_claim(
123119
const exprt &expr,
@@ -935,9 +931,7 @@ void goto_checkt::pointer_overflow_check(
935931

936932
void goto_checkt::pointer_validity_check(
937933
const dereference_exprt &expr,
938-
const guardt &guard,
939-
const exprt &access_lb,
940-
const exprt &access_ub)
934+
const guardt &guard)
941935
{
942936
if(!enable_pointer_check)
943937
return;
@@ -948,157 +942,18 @@ void goto_checkt::pointer_validity_check(
948942

949943
assert(base_type_eq(pointer_type.subtype(), expr.type(), ns));
950944

951-
local_bitvector_analysist::flagst flags=
952-
local_bitvector_analysis->get(t, pointer);
953-
954-
// For Java, we only need to check for null
955-
if(mode==ID_java)
956-
{
957-
if(flags.is_unknown() || flags.is_null())
958-
{
959-
notequal_exprt not_eq_null(pointer, null_pointer_exprt(pointer_type));
945+
auto conditions =
946+
address_check(expr.pointer(), size_of_expr(expr.type(), ns));
960947

961-
add_guarded_claim(
962-
not_eq_null,
963-
"reference is null",
964-
"pointer dereference",
965-
expr.find_source_location(),
966-
expr,
967-
guard);
968-
}
969-
}
970-
else
948+
for(const auto &c : conditions)
971949
{
972-
exprt allocs=false_exprt();
973-
974-
if(!allocations.empty())
975-
{
976-
exprt::operandst disjuncts;
977-
978-
for(const auto &a : allocations)
979-
{
980-
typecast_exprt int_ptr(pointer, a.first.type());
981-
982-
exprt lb(int_ptr);
983-
if(access_lb.is_not_nil())
984-
{
985-
if(!base_type_eq(lb.type(), access_lb.type(), ns))
986-
lb=plus_exprt(lb, typecast_exprt(access_lb, lb.type()));
987-
else
988-
lb=plus_exprt(lb, access_lb);
989-
}
990-
991-
binary_relation_exprt lb_check(a.first, ID_le, lb);
992-
993-
exprt ub(int_ptr);
994-
if(access_ub.is_not_nil())
995-
{
996-
if(!base_type_eq(ub.type(), access_ub.type(), ns))
997-
ub=plus_exprt(ub, typecast_exprt(access_ub, ub.type()));
998-
else
999-
ub=plus_exprt(ub, access_ub);
1000-
}
1001-
1002-
binary_relation_exprt ub_check(
1003-
ub, ID_le, plus_exprt(a.first, a.second));
1004-
1005-
disjuncts.push_back(and_exprt(lb_check, ub_check));
1006-
}
1007-
1008-
allocs=disjunction(disjuncts);
1009-
}
1010-
1011-
if(flags.is_unknown() ||
1012-
flags.is_null())
1013-
{
1014-
add_guarded_claim(
1015-
or_exprt(allocs, not_exprt(null_pointer(pointer))),
1016-
"dereference failure: pointer NULL",
1017-
"pointer dereference",
1018-
expr.find_source_location(),
1019-
expr,
1020-
guard);
1021-
}
1022-
1023-
if(flags.is_unknown() ||
1024-
flags.is_integer_address())
1025-
add_guarded_claim(
1026-
or_exprt(allocs, not_exprt(invalid_pointer(pointer))),
1027-
"dereference failure: pointer invalid",
1028-
"pointer dereference",
1029-
expr.find_source_location(),
1030-
expr,
1031-
guard);
1032-
1033-
if(flags.is_uninitialized())
1034-
add_guarded_claim(
1035-
or_exprt(allocs, not_exprt(invalid_pointer(pointer))),
1036-
"dereference failure: pointer uninitialized",
1037-
"pointer dereference",
1038-
expr.find_source_location(),
1039-
expr,
1040-
guard);
1041-
1042-
if(flags.is_unknown() ||
1043-
flags.is_dynamic_heap() ||
1044-
flags.is_integer_address())
1045-
add_guarded_claim(
1046-
or_exprt(allocs, not_exprt(deallocated(pointer, ns))),
1047-
"dereference failure: deallocated dynamic object",
1048-
"pointer dereference",
1049-
expr.find_source_location(),
1050-
expr,
1051-
guard);
1052-
1053-
if(flags.is_unknown() ||
1054-
flags.is_dynamic_local() ||
1055-
flags.is_integer_address())
1056-
add_guarded_claim(
1057-
or_exprt(allocs, not_exprt(dead_object(pointer, ns))),
1058-
"dereference failure: dead object",
1059-
"pointer dereference",
1060-
expr.find_source_location(),
1061-
expr,
1062-
guard);
1063-
1064-
if(flags.is_unknown() ||
1065-
flags.is_dynamic_heap() ||
1066-
flags.is_integer_address())
1067-
{
1068-
const or_exprt dynamic_bounds(
1069-
dynamic_object_lower_bound(pointer, ns, access_lb),
1070-
dynamic_object_upper_bound(pointer, ns, access_ub));
1071-
1072-
add_guarded_claim(
1073-
or_exprt(
1074-
allocs,
1075-
implies_exprt(
1076-
malloc_object(pointer, ns),
1077-
not_exprt(dynamic_bounds))),
1078-
"dereference failure: pointer outside dynamic object bounds",
1079-
"pointer dereference",
1080-
expr.find_source_location(),
1081-
expr,
1082-
guard);
1083-
}
1084-
1085-
if(flags.is_unknown() ||
1086-
flags.is_dynamic_local() ||
1087-
flags.is_static_lifetime() ||
1088-
flags.is_integer_address())
1089-
{
1090-
const or_exprt object_bounds(
1091-
object_lower_bound(pointer, ns, access_lb),
1092-
object_upper_bound(pointer, ns, access_ub));
1093-
1094-
add_guarded_claim(
1095-
or_exprt(allocs, dynamic_object(pointer), not_exprt(object_bounds)),
1096-
"dereference failure: pointer outside object bounds",
1097-
"pointer dereference",
1098-
expr.find_source_location(),
1099-
expr,
1100-
guard);
1101-
}
950+
add_guarded_claim(
951+
c.assertion,
952+
c.description,
953+
"pointer dereference",
954+
expr.find_source_location(),
955+
expr,
956+
guard);
1102957
}
1103958
}
1104959

@@ -1535,24 +1390,31 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
15351390
const dereference_exprt &deref=
15361391
to_dereference_expr(member.struct_op());
15371392

1538-
check_rec(deref.op0(), guard, false);
1393+
check_rec(deref.pointer(), guard, false);
15391394

15401395
// avoid building the following expressions when pointer_validity_check
15411396
// would return immediately anyway
15421397
if(!enable_pointer_check)
15431398
return;
15441399

1545-
exprt access_ub=nil_exprt();
1400+
// we rewrite s->member into *(s+member_offset)
1401+
// to avoid requiring memory safety of the entire struct
15461402

15471403
exprt member_offset=member_offset_expr(member, ns);
1548-
exprt size=size_of_expr(expr.type(), ns);
15491404

1550-
if(member_offset.is_not_nil() && size.is_not_nil())
1551-
access_ub=plus_exprt(member_offset, size);
1405+
if(member_offset.is_not_nil())
1406+
{
1407+
pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type());
1408+
new_pointer_type.subtype() = expr.type();
15521409

1553-
pointer_validity_check(deref, guard, member_offset, access_ub);
1410+
const exprt new_address = typecast_exprt(
1411+
plus_exprt(deref.pointer(), member_offset), new_pointer_type);
15541412

1555-
return;
1413+
const dereference_exprt new_deref(new_address, expr.type());
1414+
pointer_validity_check(new_deref, guard);
1415+
1416+
return;
1417+
}
15561418
}
15571419

15581420
forall_operands(it, expr)
@@ -1614,11 +1476,9 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
16141476
expr.id()==ID_ge || expr.id()==ID_gt)
16151477
pointer_rel_check(expr, guard);
16161478
else if(expr.id()==ID_dereference)
1617-
pointer_validity_check(
1618-
to_dereference_expr(expr),
1619-
guard,
1620-
nil_exprt(),
1621-
size_of_expr(expr.type(), ns));
1479+
{
1480+
pointer_validity_check(to_dereference_expr(expr), guard);
1481+
}
16221482
}
16231483

16241484
void goto_checkt::check(const exprt &expr)

0 commit comments

Comments
 (0)