Skip to content

Commit bb4c90b

Browse files
committed
Eliminate validity check from subset relation check
Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent b623a0b commit bb4c90b

File tree

2 files changed

+50
-49
lines changed

2 files changed

+50
-49
lines changed

regression/contracts/assigns_enforce_structs_07/test.desc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--enforce-all-contracts _ --pointer-check
44
^EXIT=10$
@@ -12,3 +12,6 @@ main.c
1212
--
1313
Checks whether CBMC properly evaluates write set of members
1414
from invalid objects. In this case, they are not writable.
15+
16+
Bug: We need to check the validity of each dereference
17+
when accessing struct members.

src/goto-instrument/contracts/assigns.cpp

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -43,52 +43,62 @@ exprt assigns_clauset::targett::normalize(const exprt &expr)
4343
exprt assigns_clauset::targett::generate_containment_check(
4444
const address_of_exprt &lhs_address) const
4545
{
46-
exprt::operandst condition;
46+
exprt::operandst address_validity;
47+
exprt::operandst containment_check;
4748

4849
// __CPROVER_w_ok(target, sizeof(target))
49-
condition.push_back(w_ok_exprt(
50+
address_validity.push_back(w_ok_exprt(
5051
address,
5152
size_of_expr(dereference_exprt(address).type(), parent.ns).value()));
5253

54+
// __CPROVER_w_ok(lhs, sizeof(lhs))
55+
address_validity.push_back(w_ok_exprt(
56+
lhs_address,
57+
size_of_expr(dereference_exprt(lhs_address).type(), parent.ns).value()));
58+
5359
// __CPROVER_same_object(lhs, target)
54-
condition.push_back(same_object(lhs_address, address));
60+
containment_check.push_back(same_object(lhs_address, address));
5561

5662
// If assigns target was a dereference, comparing objects is enough
57-
if(id == ID_dereference)
63+
// and the resulting condition will be
64+
// __CPROVER_w_ok(target, sizeof(target))
65+
// && __CPROVER_w_ok(lhs, sizeof(lhs))
66+
// ==> __CPROVER_same_object(lhs, target)
67+
if(id != ID_dereference)
5868
{
59-
// __CPROVER_w_ok(target, sizeof(target)) &&
60-
// __CPROVER_same_object(lhs, target)
61-
return conjunction(condition);
69+
const auto lhs_offset = pointer_offset(lhs_address);
70+
const auto own_offset = pointer_offset(address);
71+
72+
// __CPROVER_offset(lhs) >= __CPROVER_offset(target)
73+
containment_check.push_back(
74+
binary_relation_exprt(lhs_offset, ID_ge, own_offset));
75+
76+
const auto lhs_region = plus_exprt(
77+
typecast_exprt::conditional_cast(
78+
size_of_expr(lhs_address.object().type(), parent.ns).value(),
79+
lhs_offset.type()),
80+
lhs_offset);
81+
82+
const exprt own_region = plus_exprt(
83+
typecast_exprt::conditional_cast(
84+
size_of_expr(address.object().type(), parent.ns).value(),
85+
own_offset.type()),
86+
own_offset);
87+
88+
// (sizeof(lhs) + __CPROVER_offset(lhs)) <=
89+
// (sizeof(target) + __CPROVER_offset(target))
90+
containment_check.push_back(
91+
binary_relation_exprt(lhs_region, ID_le, own_region));
6292
}
6393

64-
const auto lhs_offset = pointer_offset(lhs_address);
65-
const auto own_offset = pointer_offset(address);
66-
67-
// __CPROVER_offset(lhs) >= __CPROVER_offset(target)
68-
condition.push_back(binary_relation_exprt(lhs_offset, ID_ge, own_offset));
69-
70-
const auto lhs_region = plus_exprt(
71-
typecast_exprt::conditional_cast(
72-
size_of_expr(lhs_address.object().type(), parent.ns).value(),
73-
lhs_offset.type()),
74-
lhs_offset);
75-
76-
const exprt own_region = plus_exprt(
77-
typecast_exprt::conditional_cast(
78-
size_of_expr(address.object().type(), parent.ns).value(),
79-
own_offset.type()),
80-
own_offset);
81-
82-
// (sizeof(lhs) + __CPROVER_offset(lhs)) <=
83-
// (sizeof(target) + __CPROVER_offset(target))
84-
condition.push_back(binary_relation_exprt(lhs_region, ID_le, own_region));
85-
86-
// __CPROVER_w_ok(target, sizeof(target)) &&
87-
// __CPROVER_same_object(lhs, target) &&
88-
// __CPROVER_offset(lhs) >= __CPROVER_offset(target) &&
89-
// (sizeof(lhs) + __CPROVER_offset(lhs)) <=
90-
// (sizeof(target) + __CPROVER_offset(target))
91-
return conjunction(condition);
94+
// __CPROVER_w_ok(target, sizeof(target))
95+
// && __CPROVER_w_ok(lhs, sizeof(lhs))
96+
// ==> __CPROVER_same_object(lhs, target)
97+
// && __CPROVER_offset(lhs) >= __CPROVER_offset(target)
98+
// && (sizeof(lhs) + __CPROVER_offset(lhs)) <=
99+
// (sizeof(target) + __CPROVER_offset(target))
100+
return binary_relation_exprt(
101+
conjunction(address_validity), ID_implies, conjunction(containment_check));
92102
}
93103

94104
assigns_clauset::assigns_clauset(
@@ -159,7 +169,6 @@ exprt assigns_clauset::generate_containment_check(const exprt &lhs) const
159169
{
160170
condition.push_back(target.generate_containment_check(lhs_address));
161171
}
162-
163172
for(const auto &target : global_write_set)
164173
{
165174
condition.push_back(target.generate_containment_check(lhs_address));
@@ -181,12 +190,6 @@ exprt assigns_clauset::generate_subset_check(
181190
exprt result = true_exprt();
182191
for(const auto &subtarget : subassigns.global_write_set)
183192
{
184-
// TODO: Optimize the implication generated due to the validity check.
185-
// In some cases, e.g. when `subtarget` is known to be `NULL`,
186-
// the implication can be skipped entirely. See #6105 for more details.
187-
auto validity_check =
188-
w_ok_exprt(subtarget.address, from_integer(0, unsigned_int_type()));
189-
190193
exprt::operandst current_subtarget_found_conditions;
191194
for(const auto &target : global_write_set)
192195
{
@@ -198,12 +201,7 @@ exprt assigns_clauset::generate_subset_check(
198201
current_subtarget_found_conditions.push_back(
199202
target.generate_containment_check(subtarget.address));
200203
}
201-
202-
auto current_subtarget_found = or_exprt(
203-
not_exprt(validity_check),
204-
disjunction(current_subtarget_found_conditions));
205-
206-
result = and_exprt(result, current_subtarget_found);
204+
result = and_exprt(result, disjunction(current_subtarget_found_conditions));
207205
}
208206

209207
return result;

0 commit comments

Comments
 (0)