Skip to content

Commit 4bbd1c9

Browse files
authored
Merge pull request #5844 from tautschnig/pointer-overflow-check
Perform pointer validity checks when doing pointer arithmetic
2 parents b1428a9 + 3acdb52 commit 4bbd1c9

File tree

7 files changed

+61
-9
lines changed

7 files changed

+61
-9
lines changed

regression/cbmc/pointer-overflow1/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ int main()
1111
p2 = p - other1;
1212
p2 = p - other2 - other1;
1313

14-
p2 = p + sizeof(int);
15-
p2 = p + sizeof(int) + sizeof(int);
14+
p2 = (char *)p + sizeof(int);
15+
p2 = (char *)p + sizeof(int) + sizeof(int);
1616

1717
return 0;
1818
}

regression/cbmc/pointer-overflow1/test.desc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ main.c
33
--pointer-overflow-check --unsigned-overflow-check
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[main\.overflow\.\d+\] line \d+ (pointer )?arithmetic overflow on .*sizeof\(signed int\) .* : SUCCESS
6+
^\[main\.overflow\.\d+\] line 8 (pointer )?arithmetic overflow on .*: FAILURE
7+
^\[main\.overflow\.\d+\] line 9 (pointer )?arithmetic overflow on .*: FAILURE
8+
^\[main\.overflow\.\d+\] line 10 (pointer )?arithmetic overflow on .*: FAILURE
9+
^\[main\.overflow\.\d+\] line 11 (pointer )?arithmetic overflow on .*: FAILURE
10+
^\[main\.overflow\.\d+\] line 12 (pointer )?arithmetic overflow on .*: FAILURE
711
^VERIFICATION FAILED$
8-
^\*\* 8 of 13 failed
912
--
10-
^\[main\.overflow\.\d+\] line \d+ (pointer )?arithmetic overflow on .*sizeof\(signed int\) .* : FAILURE
13+
^\[main\.overflow\.\d+\] line 1[45] (pointer )?arithmetic overflow on .*sizeof\(signed int\) .* : FAILURE
1114
^warning: ignoring

regression/cbmc/pointer-overflow2/main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
void main()
44
{
5+
__CPROVER_allocated_memory(9, sizeof(char));
56
char *p = (char *)10;
67
p -= 1;
78
p += 1;
8-
p += -1; // spurious pointer overflow report
9-
p -= -1; // spurious pointer overflow report
9+
p += -1; // previously: spurious pointer overflow report
10+
p -= -1; // previously: spurious pointer overflow report
1011
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
int *p = malloc(sizeof(int) * 5);
6+
int *p2 = p + 10; // undefined behavior for indexing out of bounds
7+
int *p3 = p - 10; // undefined behavior for indexing out of bounds
8+
9+
int arr[5];
10+
int *p4 = arr + 10; // undefined behavior for indexing out of bounds
11+
int *p5 = arr - 10; // undefined behavior for indexing out of bounds
12+
return 0;
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE broken-smt-backend
2+
main.c
3+
--pointer-overflow-check --no-simplify
4+
^\[main.pointer_arithmetic.\d+\] line 6 pointer arithmetic: pointer outside dynamic object bounds in p \+ \(signed (long (long )?)?int\)10: FAILURE
5+
^\[main.pointer_arithmetic.\d+\] line 7 pointer arithmetic: pointer outside dynamic object bounds in p - \(signed (long (long )?)?int\)10: FAILURE
6+
^\[main.pointer_arithmetic.\d+\] line 10 pointer arithmetic: pointer outside object bounds in arr \+ \(signed (long (long )?)?int\)10: FAILURE
7+
^\[main.pointer_arithmetic.\d+\] line 11 pointer arithmetic: pointer outside object bounds in arr - \(signed (long (long )?)?int\)10: FAILURE
8+
^\*\* 4 of \d+ failed
9+
^VERIFICATION FAILED$
10+
^EXIT=10$
11+
^SIGNAL=0$
12+
--
13+
^warning: ignoring
14+
Invariant check failed
15+
--
16+
Uses --no-simplify to avoid removing repeated ASSERT FALSE statements.

src/analyses/goto_check.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,12 @@ class goto_checkt
286286
void goto_checkt::collect_allocations(
287287
const goto_functionst &goto_functions)
288288
{
289-
if(!enable_pointer_check && !enable_bounds_check)
289+
if(
290+
!enable_pointer_check && !enable_bounds_check &&
291+
!enable_pointer_overflow_check)
292+
{
290293
return;
294+
}
291295

292296
for(const auto &gf_entry : goto_functions.function_map)
293297
{
@@ -1188,6 +1192,21 @@ void goto_checkt::pointer_overflow_check(
11881192
expr.find_source_location(),
11891193
expr,
11901194
guard);
1195+
1196+
// the result must be within object bounds or one past the end
1197+
const auto size = from_integer(0, size_type());
1198+
auto conditions = get_pointer_dereferenceable_conditions(expr, size);
1199+
1200+
for(const auto &c : conditions)
1201+
{
1202+
add_guarded_property(
1203+
c.assertion,
1204+
"pointer arithmetic: " + c.description,
1205+
"pointer arithmetic",
1206+
expr.find_source_location(),
1207+
expr,
1208+
guard);
1209+
}
11911210
}
11921211

11931212
void goto_checkt::pointer_validity_check(

src/solvers/flattening/bv_pointers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
507507

508508
const bvt &bv = convert_bv(minus_expr.lhs());
509509

510-
typet pointer_sub_type = minus_expr.rhs().type().subtype();
510+
typet pointer_sub_type = minus_expr.lhs().type().subtype();
511511
mp_integer element_size;
512512

513513
if(pointer_sub_type.id()==ID_empty)

0 commit comments

Comments
 (0)