|
13 | 13 |
|
14 | 14 | #include <algorithm>
|
15 | 15 |
|
16 |
| -#include <util/simplify_expr.h> |
17 |
| -#include <util/array_name.h> |
18 |
| -#include <util/ieee_float.h> |
19 | 16 | #include <util/arith_tools.h>
|
| 17 | +#include <util/array_name.h> |
| 18 | +#include <util/base_type.h> |
| 19 | +#include <util/cprover_prefix.h> |
| 20 | +#include <util/c_types.h> |
20 | 21 | #include <util/expr_util.h>
|
21 | 22 | #include <util/find_symbols.h>
|
22 |
| -#include <util/std_expr.h> |
23 |
| -#include <util/std_types.h> |
24 | 23 | #include <util/guard.h>
|
25 |
| -#include <util/base_type.h> |
| 24 | +#include <util/ieee_float.h> |
| 25 | +#include <util/options.h> |
26 | 26 | #include <util/pointer_offset_size.h>
|
27 | 27 | #include <util/pointer_predicates.h>
|
28 |
| -#include <util/cprover_prefix.h> |
29 |
| -#include <util/options.h> |
| 28 | +#include <util/simplify_expr.h> |
| 29 | +#include <util/std_expr.h> |
| 30 | +#include <util/std_types.h> |
30 | 31 |
|
31 | 32 | #include <langapi/language.h>
|
32 | 33 | #include <langapi/mode.h>
|
@@ -99,25 +100,21 @@ class goto_checkt
|
99 | 100 |
|
100 | 101 | using conditionst = std::list<conditiont>;
|
101 | 102 |
|
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); |
| 103 | + void bounds_check(const index_exprt &, const guardt &); |
| 104 | + void div_by_zero_check(const div_exprt &, const guardt &); |
| 105 | + void mod_by_zero_check(const mod_exprt &, const guardt &); |
| 106 | + void undefined_shift_check(const shift_exprt &, const guardt &); |
| 107 | + void pointer_rel_check(const exprt &, const guardt &); |
| 108 | + void pointer_overflow_check(const exprt &, const guardt &); |
| 109 | + void pointer_validity_check(const dereference_exprt &, const guardt &); |
113 | 110 | 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); |
| 111 | + void integer_overflow_check(const exprt &, const guardt &); |
| 112 | + void conversion_check(const exprt &, const guardt &); |
| 113 | + void float_overflow_check(const exprt &, const guardt &); |
| 114 | + void nan_check(const exprt &, const guardt &); |
| 115 | + void rw_ok_check(exprt &); |
119 | 116 |
|
120 |
| - std::string array_name(const exprt &expr); |
| 117 | + std::string array_name(const exprt &); |
121 | 118 |
|
122 | 119 | void add_guarded_claim(
|
123 | 120 | const exprt &expr,
|
@@ -935,177 +932,25 @@ void goto_checkt::pointer_overflow_check(
|
935 | 932 |
|
936 | 933 | void goto_checkt::pointer_validity_check(
|
937 | 934 | const dereference_exprt &expr,
|
938 |
| - const guardt &guard, |
939 |
| - const exprt &access_lb, |
940 |
| - const exprt &access_ub) |
| 935 | + const guardt &guard) |
941 | 936 | {
|
942 | 937 | if(!enable_pointer_check)
|
943 | 938 | return;
|
944 | 939 |
|
945 |
| - const exprt &pointer=expr.op0(); |
946 |
| - const pointer_typet &pointer_type= |
947 |
| - to_pointer_type(ns.follow(pointer.type())); |
948 |
| - |
949 |
| - assert(base_type_eq(pointer_type.subtype(), expr.type(), ns)); |
| 940 | + const exprt &pointer=expr.pointer(); |
950 | 941 |
|
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)); |
| 942 | + auto conditions = |
| 943 | + address_check(pointer, size_of_expr(expr.type(), ns)); |
960 | 944 |
|
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 |
| 945 | + for(const auto &c : conditions) |
971 | 946 | {
|
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 |
| - add_guarded_claim( |
1025 |
| - or_exprt(allocs, not_exprt(invalid_pointer(pointer))), |
1026 |
| - "dereference failure: pointer invalid", |
1027 |
| - "pointer dereference", |
1028 |
| - expr.find_source_location(), |
1029 |
| - expr, |
1030 |
| - guard); |
1031 |
| - |
1032 |
| - if(flags.is_uninitialized()) |
1033 |
| - add_guarded_claim( |
1034 |
| - or_exprt(allocs, not_exprt(invalid_pointer(pointer))), |
1035 |
| - "dereference failure: pointer uninitialized", |
1036 |
| - "pointer dereference", |
1037 |
| - expr.find_source_location(), |
1038 |
| - expr, |
1039 |
| - guard); |
1040 |
| - |
1041 |
| - if(flags.is_unknown() || |
1042 |
| - flags.is_dynamic_heap()) |
1043 |
| - add_guarded_claim( |
1044 |
| - or_exprt(allocs, not_exprt(deallocated(pointer, ns))), |
1045 |
| - "dereference failure: deallocated dynamic object", |
1046 |
| - "pointer dereference", |
1047 |
| - expr.find_source_location(), |
1048 |
| - expr, |
1049 |
| - guard); |
1050 |
| - |
1051 |
| - if(flags.is_unknown() || |
1052 |
| - flags.is_dynamic_local()) |
1053 |
| - add_guarded_claim( |
1054 |
| - or_exprt(allocs, not_exprt(dead_object(pointer, ns))), |
1055 |
| - "dereference failure: dead object", |
1056 |
| - "pointer dereference", |
1057 |
| - expr.find_source_location(), |
1058 |
| - expr, |
1059 |
| - guard); |
1060 |
| - |
1061 |
| - if(flags.is_unknown() || |
1062 |
| - flags.is_dynamic_heap()) |
1063 |
| - { |
1064 |
| - const or_exprt dynamic_bounds( |
1065 |
| - dynamic_object_lower_bound(pointer, ns, access_lb), |
1066 |
| - dynamic_object_upper_bound(pointer, ns, access_ub)); |
1067 |
| - |
1068 |
| - add_guarded_claim( |
1069 |
| - or_exprt( |
1070 |
| - allocs, |
1071 |
| - implies_exprt( |
1072 |
| - malloc_object(pointer, ns), |
1073 |
| - not_exprt(dynamic_bounds))), |
1074 |
| - "dereference failure: pointer outside dynamic object bounds", |
1075 |
| - "pointer dereference", |
1076 |
| - expr.find_source_location(), |
1077 |
| - expr, |
1078 |
| - guard); |
1079 |
| - } |
1080 |
| - |
1081 |
| - if(flags.is_unknown() || |
1082 |
| - flags.is_dynamic_local() || |
1083 |
| - flags.is_static_lifetime()) |
1084 |
| - { |
1085 |
| - const or_exprt object_bounds( |
1086 |
| - object_lower_bound(pointer, ns, access_lb), |
1087 |
| - object_upper_bound(pointer, ns, access_ub)); |
1088 |
| - |
1089 |
| - add_guarded_claim( |
1090 |
| - or_exprt(allocs, dynamic_object(pointer), not_exprt(object_bounds)), |
1091 |
| - "dereference failure: pointer outside object bounds", |
1092 |
| - "pointer dereference", |
1093 |
| - expr.find_source_location(), |
1094 |
| - expr, |
1095 |
| - guard); |
1096 |
| - } |
1097 |
| - |
1098 |
| - if(flags.is_unknown() || |
1099 |
| - flags.is_integer_address()) |
1100 |
| - { |
1101 |
| - add_guarded_claim( |
1102 |
| - implies_exprt(integer_address(pointer), allocs), |
1103 |
| - "dereference failure: invalid integer address", |
1104 |
| - "pointer dereference", |
1105 |
| - expr.find_source_location(), |
1106 |
| - expr, |
1107 |
| - guard); |
1108 |
| - } |
| 947 | + add_guarded_claim( |
| 948 | + c.assertion, |
| 949 | + "dereference failure: "+c.description, |
| 950 | + "pointer dereference", |
| 951 | + expr.find_source_location(), |
| 952 | + expr, |
| 953 | + guard); |
1109 | 954 | }
|
1110 | 955 | }
|
1111 | 956 |
|
@@ -1207,7 +1052,7 @@ goto_checkt::address_check(const exprt &address, const exprt &size)
|
1207 | 1052 |
|
1208 | 1053 | conditions.push_back(conditiont(
|
1209 | 1054 | implies_exprt(not_exprt(dynamic_object(address)), not_exprt(object_bounds_violation)),
|
1210 |
| - "dereference failure: pointer outside object bounds")); |
| 1055 | + "pointer outside object bounds")); |
1211 | 1056 | }
|
1212 | 1057 |
|
1213 | 1058 | if(flags.is_unknown() || flags.is_integer_address())
|
@@ -1547,24 +1392,38 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
|
1547 | 1392 | const dereference_exprt &deref=
|
1548 | 1393 | to_dereference_expr(member.struct_op());
|
1549 | 1394 |
|
1550 |
| - check_rec(deref.op0(), guard, false); |
| 1395 | + check_rec(deref.pointer(), guard, false); |
1551 | 1396 |
|
1552 | 1397 | // avoid building the following expressions when pointer_validity_check
|
1553 | 1398 | // would return immediately anyway
|
1554 | 1399 | if(!enable_pointer_check)
|
1555 | 1400 | return;
|
1556 | 1401 |
|
1557 |
| - exprt access_ub=nil_exprt(); |
| 1402 | + // we rewrite s->member into *(s+member_offset) |
| 1403 | + // to avoid requiring memory safety of the entire struct |
1558 | 1404 |
|
1559 | 1405 | exprt member_offset=member_offset_expr(member, ns);
|
1560 |
| - exprt size=size_of_expr(expr.type(), ns); |
1561 | 1406 |
|
1562 |
| - if(member_offset.is_not_nil() && size.is_not_nil()) |
1563 |
| - access_ub=plus_exprt(member_offset, size); |
| 1407 | + if(member_offset.is_not_nil()) |
| 1408 | + { |
| 1409 | + pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type()); |
| 1410 | + new_pointer_type.subtype() = expr.type(); |
1564 | 1411 |
|
1565 |
| - pointer_validity_check(deref, guard, member_offset, access_ub); |
| 1412 | + const exprt char_pointer = |
| 1413 | + typecast_exprt::conditional_cast(deref.pointer(), pointer_type(char_type())); |
1566 | 1414 |
|
1567 |
| - return; |
| 1415 | + const exprt new_address = typecast_exprt( |
| 1416 | + plus_exprt(char_pointer, member_offset), char_pointer.type()); |
| 1417 | + |
| 1418 | + const exprt new_address_casted = |
| 1419 | + typecast_exprt::conditional_cast(new_address, new_pointer_type); |
| 1420 | + |
| 1421 | + dereference_exprt new_deref(new_address_casted, expr.type()); |
| 1422 | + new_deref.add_source_location() = deref.source_location(); |
| 1423 | + pointer_validity_check(new_deref, guard); |
| 1424 | + |
| 1425 | + return; |
| 1426 | + } |
1568 | 1427 | }
|
1569 | 1428 |
|
1570 | 1429 | forall_operands(it, expr)
|
@@ -1626,11 +1485,9 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
|
1626 | 1485 | expr.id()==ID_ge || expr.id()==ID_gt)
|
1627 | 1486 | pointer_rel_check(expr, guard);
|
1628 | 1487 | else if(expr.id()==ID_dereference)
|
1629 |
| - pointer_validity_check( |
1630 |
| - to_dereference_expr(expr), |
1631 |
| - guard, |
1632 |
| - nil_exprt(), |
1633 |
| - size_of_expr(expr.type(), ns)); |
| 1488 | + { |
| 1489 | + pointer_validity_check(to_dereference_expr(expr), guard); |
| 1490 | + } |
1634 | 1491 | }
|
1635 | 1492 |
|
1636 | 1493 | void goto_checkt::check(const exprt &expr)
|
|
0 commit comments