@@ -72,6 +72,8 @@ class goto_checkt
7272 enable_built_in_assertions=_options.get_bool_option (" built-in-assertions" );
7373 enable_assumptions=_options.get_bool_option (" assumptions" );
7474 error_labels=_options.get_list_option (" error-label" );
75+ enable_pointer_primitive_check =
76+ _options.get_bool_option (" pointer-primitive-check" );
7577 }
7678
7779 typedef goto_functionst::goto_functiont goto_functiont;
@@ -185,6 +187,20 @@ class goto_checkt
185187 const exprt &src_expr,
186188 const guardt &guard);
187189
190+ // / Generates VCCs to check that pointers passed to pointer primitives are
191+ // / either null or valid
192+ // /
193+ // / \param expr: the pointer primitive expression
194+ // / \param guard: the condition under which the operation happens
195+ void pointer_primitive_check (const exprt &expr, const guardt &guard);
196+
197+ // / Returns true if the given expression is a pointer primitive such as
198+ // / __CPROVER_r_ok()
199+ // /
200+ // / \param expr expression
201+ // / \return true if the given expression is a pointer primitive
202+ bool is_pointer_primitive (const exprt &expr);
203+
188204 conditionst address_check (const exprt &address, const exprt &size);
189205 void integer_overflow_check (const exprt &, const guardt &);
190206 void conversion_check (const exprt &, const guardt &);
@@ -238,6 +254,7 @@ class goto_checkt
238254 bool enable_assertions;
239255 bool enable_built_in_assertions;
240256 bool enable_assumptions;
257+ bool enable_pointer_primitive_check;
241258
242259 typedef optionst::value_listt error_labelst;
243260 error_labelst error_labels;
@@ -1163,6 +1180,53 @@ void goto_checkt::pointer_validity_check(
11631180 }
11641181}
11651182
1183+ void goto_checkt::pointer_primitive_check (
1184+ const exprt &expr,
1185+ const guardt &guard)
1186+ {
1187+ if (!enable_pointer_primitive_check)
1188+ return ;
1189+
1190+ const exprt pointer = (expr.id () == ID_r_ok || expr.id () == ID_w_ok)
1191+ ? to_binary_expr (expr).lhs ()
1192+ : to_unary_expr (expr).op ();
1193+
1194+ CHECK_RETURN (pointer.type ().id () == ID_pointer);
1195+
1196+ const auto size_of_expr_opt = size_of_expr (pointer.type ().subtype (), ns);
1197+
1198+ const exprt size = !size_of_expr_opt.has_value ()
1199+ ? from_integer (1 , size_type ())
1200+ : size_of_expr_opt.value ();
1201+
1202+ const conditionst &conditions = address_check (pointer, size);
1203+
1204+ exprt::operandst conjuncts;
1205+
1206+ for (const auto &c : conditions)
1207+ conjuncts.push_back (c.assertion );
1208+
1209+ const or_exprt or_expr (null_object (pointer), conjunction (conjuncts));
1210+
1211+ add_guarded_property (
1212+ or_expr,
1213+ " pointer in pointer primitive is neither null nor valid" ,
1214+ " pointer primitives" ,
1215+ expr.source_location (),
1216+ expr,
1217+ guard);
1218+ }
1219+
1220+ bool goto_checkt::is_pointer_primitive (const exprt &expr)
1221+ {
1222+ // we don't need to include the __CPROVER_same_object primitive here as it
1223+ // is replaced by lower level primitives in the special function handling
1224+ // during typechecking (see c_typecheck_expr.cpp)
1225+ return expr.id () == ID_pointer_object || expr.id () == ID_pointer_offset ||
1226+ expr.id () == ID_object_size || expr.id () == ID_r_ok ||
1227+ expr.id () == ID_w_ok || expr.id () == ID_is_dynamic_object;
1228+ }
1229+
11661230goto_checkt::conditionst
11671231goto_checkt::address_check (const exprt &address, const exprt &size)
11681232{
@@ -1740,6 +1804,10 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard)
17401804 {
17411805 pointer_validity_check (to_dereference_expr (expr), expr, guard);
17421806 }
1807+ else if (is_pointer_primitive (expr))
1808+ {
1809+ pointer_primitive_check (expr, guard);
1810+ }
17431811}
17441812
17451813void goto_checkt::check (const exprt &expr)
@@ -1860,6 +1928,8 @@ void goto_checkt::goto_check(
18601928 flag_resetter.set_flag (enable_undefined_shift_check, false );
18611929 else if (d.first == " disable:nan-check" )
18621930 flag_resetter.set_flag (enable_nan_check, false );
1931+ else if (d.first == " disable:pointer-primitive-check" )
1932+ flag_resetter.set_flag (enable_pointer_primitive_check, false );
18631933 }
18641934
18651935 new_code.clear ();
@@ -2049,7 +2119,7 @@ void goto_checkt::goto_check(
20492119 }
20502120 else if (i.is_dead ())
20512121 {
2052- if (enable_pointer_check)
2122+ if (enable_pointer_check || enable_pointer_primitive_check )
20532123 {
20542124 assert (i.code .operands ().size ()==1 );
20552125 const symbol_exprt &variable=to_symbol_expr (i.code .op0 ());
0 commit comments