Skip to content

Commit cc2346c

Browse files
committed
Pointer subtraction requires same-object and valid-pointer property
Subtracting pointers not pointing into the same (array) object (or one byte past the object) is undefined behaviour.
1 parent 2da9723 commit cc2346c

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

regression/cbmc-library/posix_memalign-02/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ main.c
66
^VERIFICATION FAILED$
77
\[main.precondition_instance.1\] .* memcpy src/dst overlap: FAILURE
88
\[main.precondition_instance.3\] .* memcpy destination region writeable: FAILURE
9-
\*\* 2 of 14 failed
109
--
1110
^warning: ignoring
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int main()
2+
{
3+
int array[2];
4+
int other_array[2];
5+
6+
int diff = array - other_array;
7+
8+
return 0;
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
^\[main.pointer.1\] line 6 same object violation in array - other_array: FAILURE$
5+
^VERIFICATION FAILED$
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
^CONVERSION ERROR$

src/analyses/goto_check.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class goto_checkt
178178
void mod_overflow_check(const mod_exprt &, const guardt &);
179179
void enum_range_check(const exprt &, const guardt &);
180180
void undefined_shift_check(const shift_exprt &, const guardt &);
181-
void pointer_rel_check(const binary_relation_exprt &, const guardt &);
181+
void pointer_rel_check(const binary_exprt &, const guardt &);
182182
void pointer_overflow_check(const exprt &, const guardt &);
183183

184184
/// Generates VCCs for the validity of the given dereferencing operation.
@@ -1117,7 +1117,7 @@ void goto_checkt::nan_check(
11171117
}
11181118

11191119
void goto_checkt::pointer_rel_check(
1120-
const binary_relation_exprt &expr,
1120+
const binary_exprt &expr,
11211121
const guardt &guard)
11221122
{
11231123
if(!enable_pointer_check)
@@ -1137,6 +1137,25 @@ void goto_checkt::pointer_rel_check(
11371137
expr.find_source_location(),
11381138
expr,
11391139
guard);
1140+
1141+
for(const auto &pointer : expr.operands())
1142+
{
1143+
// just this particular byte must be within object bounds or one past the
1144+
// end
1145+
const auto size = from_integer(0, size_type());
1146+
auto conditions = get_pointer_dereferenceable_conditions(pointer, size);
1147+
1148+
for(const auto &c : conditions)
1149+
{
1150+
add_guarded_property(
1151+
c.assertion,
1152+
"pointer relation: " + c.description,
1153+
"pointer arithmetic",
1154+
expr.find_source_location(),
1155+
pointer,
1156+
guard);
1157+
}
1158+
}
11401159
}
11411160
}
11421161

@@ -1647,6 +1666,14 @@ void goto_checkt::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
16471666
if(expr.type().id() == ID_signedbv || expr.type().id() == ID_unsignedbv)
16481667
{
16491668
integer_overflow_check(expr, guard);
1669+
1670+
if(
1671+
expr.operands().size() == 2 && expr.id() == ID_minus &&
1672+
expr.operands()[0].type().id() == ID_pointer &&
1673+
expr.operands()[1].type().id() == ID_pointer)
1674+
{
1675+
pointer_rel_check(to_binary_expr(expr), guard);
1676+
}
16501677
}
16511678
else if(expr.type().id() == ID_floatbv)
16521679
{

0 commit comments

Comments
 (0)