@@ -86,6 +86,20 @@ class goto_checkt
86
86
bool address);
87
87
void check (const exprt &expr);
88
88
89
+ struct conditiont
90
+ {
91
+ conditiont (const exprt &_assertion, const std::string &_description):
92
+ assertion (_assertion),
93
+ description (_description)
94
+ {
95
+ }
96
+
97
+ exprt assertion;
98
+ std::string description;
99
+ };
100
+
101
+ using conditionst=std::list<conditiont>;
102
+
89
103
void bounds_check (const index_exprt &expr, const guardt &guard);
90
104
void div_by_zero_check (const div_exprt &expr, const guardt &guard);
91
105
void mod_by_zero_check (const mod_exprt &expr, const guardt &guard);
@@ -97,10 +111,14 @@ class goto_checkt
97
111
const guardt &guard,
98
112
const exprt &access_lb,
99
113
const exprt &access_ub);
114
+ conditionst address_check (
115
+ const exprt &address,
116
+ const exprt &size);
100
117
void integer_overflow_check (const exprt &expr, const guardt &guard);
101
118
void conversion_check (const exprt &expr, const guardt &guard);
102
119
void float_overflow_check (const exprt &expr, const guardt &guard);
103
120
void nan_check (const exprt &expr, const guardt &guard);
121
+ void rw_ok_check (exprt &expr);
104
122
105
123
std::string array_name (const exprt &expr);
106
124
@@ -139,6 +157,8 @@ class goto_checkt
139
157
typedef optionst::value_listt error_labelst;
140
158
error_labelst error_labels;
141
159
160
+ // the first element of the pair is the base address,
161
+ // and the second is the size of the region
142
162
typedef std::pair<exprt, exprt> allocationt;
143
163
typedef std::list<allocationt> allocationst;
144
164
allocationst allocations;
@@ -1076,6 +1096,139 @@ void goto_checkt::pointer_validity_check(
1076
1096
}
1077
1097
}
1078
1098
1099
+ goto_checkt::conditionst goto_checkt::address_check (
1100
+ const exprt &address,
1101
+ const exprt &size)
1102
+ {
1103
+ if (!enable_pointer_check)
1104
+ return {};
1105
+
1106
+ PRECONDITION (address.type ().id ()==ID_pointer);
1107
+ const auto &pointer_type=to_pointer_type (address.type ());
1108
+
1109
+ local_bitvector_analysist::flagst flags=
1110
+ local_bitvector_analysis->get (t, address);
1111
+
1112
+ // For Java, we only need to check for null
1113
+ if (mode==ID_java)
1114
+ {
1115
+ if (flags.is_unknown () || flags.is_null ())
1116
+ {
1117
+ notequal_exprt not_eq_null (address, null_pointer_exprt (pointer_type));
1118
+
1119
+ return { conditiont (not_eq_null, " reference is null" ) };
1120
+ }
1121
+ else
1122
+ return {};
1123
+ }
1124
+ else
1125
+ {
1126
+ conditionst conditions;
1127
+ exprt::operandst alloc_disjuncts;
1128
+
1129
+ for (const auto &a : allocations)
1130
+ {
1131
+ typecast_exprt int_ptr (address, a.first .type ());
1132
+
1133
+ #if 0
1134
+ exprt lb(int_ptr);
1135
+ if(access_lb.is_not_nil())
1136
+ {
1137
+ if(!base_type_eq(lb.type(), access_lb.type(), ns))
1138
+ lb=plus_exprt(lb, typecast_exprt(access_lb, lb.type()));
1139
+ else
1140
+ lb=plus_exprt(lb, access_lb);
1141
+ }
1142
+
1143
+ binary_relation_exprt lb_check(a.first, ID_le, lb);
1144
+
1145
+ exprt ub(int_ptr);
1146
+ if(access_ub.is_not_nil())
1147
+ {
1148
+ if(!base_type_eq(ub.type(), access_ub.type(), ns))
1149
+ ub=plus_exprt(ub, typecast_exprt(access_ub, ub.type()));
1150
+ else
1151
+ ub=plus_exprt(ub, access_ub);
1152
+ }
1153
+
1154
+ binary_relation_exprt ub_check(
1155
+ ub, ID_le, plus_exprt(a.first, a.second));
1156
+
1157
+ alloc_disjuncts.push_back(and_exprt(lb_check, ub_check));
1158
+ #endif
1159
+ }
1160
+
1161
+ const exprt allocs=disjunction (alloc_disjuncts);
1162
+
1163
+ if (flags.is_unknown () || flags.is_null ())
1164
+ conditions.push_back (conditiont (
1165
+ or_exprt (allocs, not_exprt (null_pointer (address))),
1166
+ " pointer NULL" ));
1167
+
1168
+ if (flags.is_unknown ())
1169
+ conditions.push_back (conditiont (
1170
+ or_exprt (allocs, not_exprt (invalid_pointer (address))),
1171
+ " pointer invalid" ));
1172
+
1173
+ if (flags.is_uninitialized ())
1174
+ conditions.push_back (conditiont (
1175
+ or_exprt (allocs, not_exprt (invalid_pointer (address))),
1176
+ " pointer uninitialized" ));
1177
+
1178
+ if (flags.is_unknown () || flags.is_dynamic_heap ())
1179
+ conditions.push_back (conditiont (
1180
+ or_exprt (allocs, not_exprt (deallocated (address, ns))),
1181
+ " deallocated dynamic object" ));
1182
+
1183
+ if (flags.is_unknown () || flags.is_dynamic_local ())
1184
+ conditions.push_back (conditiont (
1185
+ or_exprt (allocs, not_exprt (dead_object (address, ns))),
1186
+ " dead object" ));
1187
+
1188
+ if (flags.is_unknown () || flags.is_dynamic_heap ())
1189
+ {
1190
+ #if 0
1191
+ const or_exprt dynamic_bounds(
1192
+ dynamic_object_lower_bound(address, ns, access_lb),
1193
+ dynamic_object_upper_bound(address, dereference_type, ns, access_ub));
1194
+
1195
+ add_guarded_claim(
1196
+ or_exprt(
1197
+ allocs,
1198
+ implies_exprt(
1199
+ malloc_object(address, ns),
1200
+ not_exprt(dynamic_bounds))),
1201
+ "dereference failure: pointer outside dynamic object bounds",
1202
+ "pointer dereference",
1203
+ expr.find_source_location(),
1204
+ expr,
1205
+ guard);
1206
+ #endif
1207
+ }
1208
+
1209
+ if (flags.is_unknown () ||
1210
+ flags.is_dynamic_local () ||
1211
+ flags.is_static_lifetime ())
1212
+ {
1213
+ #if 0
1214
+ const or_exprt object_bounds(
1215
+ object_lower_bound(address, ns, access_lb),
1216
+ object_upper_bound(address, dereference_type, ns, access_ub));
1217
+
1218
+ add_guarded_claim(
1219
+ or_exprt(allocs, dynamic_object(address), not_exprt(object_bounds)),
1220
+ "dereference failure: pointer outside object bounds",
1221
+ "pointer dereference",
1222
+ expr.find_source_location(),
1223
+ expr,
1224
+ guard);
1225
+ #endif
1226
+ }
1227
+
1228
+ return conditions;
1229
+ }
1230
+ }
1231
+
1079
1232
std::string goto_checkt::array_name (const exprt &expr)
1080
1233
{
1081
1234
return ::array_name (ns, expr);
@@ -1494,6 +1647,27 @@ void goto_checkt::check(const exprt &expr)
1494
1647
check_rec (expr, guard, false );
1495
1648
}
1496
1649
1650
+ // / expand the r_ok and w_ok predicates
1651
+ void goto_checkt::rw_ok_check (exprt &expr)
1652
+ {
1653
+ for (auto &op : expr.operands ())
1654
+ rw_ok_check (op);
1655
+
1656
+ if (expr.id ()==ID_r_ok || expr.id ()==ID_w_ok)
1657
+ {
1658
+ // these get an address as first argument and a size as second
1659
+ DATA_INVARIANT (expr.operands ().size ()==2 ,
1660
+ " r/w_ok must have two operands" );
1661
+
1662
+ const auto conditions=address_check (expr.op0 (), expr.op1 ());
1663
+ exprt::operandst conjuncts;
1664
+ for (const auto &c : conditions)
1665
+ conjuncts.push_back (c.assertion );
1666
+
1667
+ expr=conjunction (conjuncts);
1668
+ }
1669
+ }
1670
+
1497
1671
void goto_checkt::goto_check (
1498
1672
goto_functiont &goto_function,
1499
1673
const irep_idt &_mode)
@@ -1643,6 +1817,9 @@ void goto_checkt::goto_check(
1643
1817
else if (i.is_assert ())
1644
1818
{
1645
1819
bool is_user_provided=i.source_location .get_bool (" user-provided" );
1820
+
1821
+ rw_ok_check (i.guard );
1822
+
1646
1823
if ((is_user_provided && !enable_assertions &&
1647
1824
i.source_location .get_property_class ()!=" error label" ) ||
1648
1825
(!is_user_provided && !enable_built_in_assertions))
0 commit comments