Skip to content

Commit b11f7a8

Browse files
authored
Merge pull request #1768 from goblint/issue-1762
Fix pointer arithmethic on NULL
2 parents 6b1f72b + 0bffa2c commit b11f7a8

File tree

4 files changed

+67
-13
lines changed

4 files changed

+67
-13
lines changed

src/analyses/base.ml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ struct
200200
| PlusA -> ID.add
201201
| MinusA -> ID.sub
202202
| Mult -> ID.mul
203-
| Div ->
203+
| Div ->
204204
fun x y ->
205205
(match ID.equal_to Z.zero y with
206206
| `Eq ->
@@ -209,7 +209,7 @@ struct
209209
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division might be zero"
210210
| `Neq -> ());
211211
ID.div x y
212-
| Mod ->
212+
| Mod ->
213213
fun x y ->
214214
(match ID.equal_to Z.zero y with
215215
| `Eq ->
@@ -303,24 +303,33 @@ struct
303303
`Field(f, addToOffset n t' o)
304304
| `NoOffset -> `Index(iDtoIdx n, `NoOffset)
305305
in
306-
let default = function
307-
| Addr.NullPtr when GobOption.exists (Z.equal Z.zero) (ID.to_int n) -> Addr.NullPtr
308-
| _ -> Addr.UnknownPtr
309-
in
310-
match Addr.to_mval addr with
311-
| Some (x, o) -> Addr.of_mval (x, addToOffset n (Some x.vtype) o)
312-
| None -> default addr
306+
match addr with
307+
| Addr (x, o) -> AD.of_mval (x, addToOffset n (Some x.vtype) o)
308+
| NullPtr ->
309+
begin match ID.equal_to Z.zero n with
310+
| `Eq -> AD.null_ptr
311+
| `Neq -> AD.unknown_ptr
312+
| `Top -> AD.top_ptr
313+
end
314+
| UnknownPtr
315+
| StrPtr _ ->
316+
begin match ID.equal_to Z.zero n with
317+
| `Eq -> AD.singleton addr (* remains unchanged *)
318+
| `Neq
319+
| `Top -> AD.top_ptr
320+
end
313321
in
322+
let ad_concat_map f a = AD.fold (fun a acc -> AD.join (f a) acc) a (AD.empty ()) in
314323
let addToAddrOp p (n:ID.t):value =
315324
match op with
316325
(* For array indexing e[i] and pointer addition e + i we have: *)
317326
| IndexPI | PlusPI ->
318-
Address (AD.map (addToAddr n) p)
327+
Address (ad_concat_map (addToAddr n) p)
319328
(* Pointer subtracted by a value (e-i) is very similar *)
320329
(* Cast n to the (signed) ptrdiff_ikind, then add the its negated value. *)
321330
| MinusPI ->
322331
let n = ID.neg (ID.cast_to (Cilfacade.ptrdiff_ikind ()) n) in
323-
Address (AD.map (addToAddr n) p)
332+
Address (ad_concat_map (addToAddr n) p)
324333
| Mod -> Int (ID.top_of (Cilfacade.ptrdiff_ikind ())) (* we assume that address is actually casted to int first*)
325334
| _ -> Address AD.top_ptr
326335
in
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
int main(void) {
2+
int *p;
3+
int i;
4+
int *q = p + i;
5+
*q = 42; // WARN (may NULL dereference)
6+
7+
if (p) {
8+
q = p + i;
9+
*q = 42; // WARN (may NULL dereference)
10+
11+
if (i == 0) {
12+
q = p + i;
13+
*q = 42; // NOWARN (no NULL dereference)
14+
}
15+
else {
16+
q = p + i;
17+
*q = 42; // WARN (may NULL dereference)
18+
}
19+
}
20+
}

tests/regression/55-loop-unrolling/12-loop-no-overflows.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// PARAM: --enable ana.int.interval_set
22
// extracted from SV-COMP task ldv-memsafety/memleaks_test12-2.i
3-
3+
// CRAM
44
typedef unsigned int size_t;
55
struct ldv_list_head {
66
struct ldv_list_head *next, *prev;
@@ -29,7 +29,7 @@ void ldv_msg_free(struct ldv_msg *msg) {
2929
void main(void) {
3030
struct ldv_msg *msg;
3131
struct ldv_msg *n;
32-
for (msg = ({ const typeof( ((typeof(*msg) *)0)->list ) *__mptr = ((&ldv_global_msg_list)->next); (typeof(*msg) *)( (char *)__mptr - ((size_t) &((typeof(*msg) *)0)->list) ); }), n = ({ const typeof( ((typeof(*(msg)) *)0)->list ) *__mptr = ((msg)->list.next); (typeof(*(msg)) *)( (char *)__mptr - ((size_t) &((typeof(*(msg)) *)0)->list) ); }); &msg->list != (&ldv_global_msg_list); msg = n, n = ({ const typeof( ((typeof(*(n)) *)0)->list ) *__mptr = ((n)->list.next); (typeof(*(n)) *)( (char *)__mptr - ((size_t) &((typeof(*(n)) *)0)->list) ); })) // NOWARN
32+
for (msg = ({ const typeof( ((typeof(*msg) *)0)->list ) *__mptr = ((&ldv_global_msg_list)->next); (typeof(*msg) *)( (char *)__mptr - ((size_t) &((typeof(*msg) *)0)->list) ); }), n = ({ const typeof( ((typeof(*(msg)) *)0)->list ) *__mptr = ((msg)->list.next); (typeof(*(msg)) *)( (char *)__mptr - ((size_t) &((typeof(*(msg)) *)0)->list) ); }); &msg->list != (&ldv_global_msg_list); msg = n, n = ({ const typeof( ((typeof(*(n)) *)0)->list ) *__mptr = ((n)->list.next); (typeof(*(n)) *)( (char *)__mptr - ((size_t) &((typeof(*(n)) *)0)->list) ); }))
3333
{
3434
ldv_list_del(&msg->list);
3535
ldv_msg_free(msg);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Should have no overflow warning (on line 32).
2+
Now has NULL dereference warning there still.
3+
4+
$ goblint --enable ana.int.interval_set 12-loop-no-overflows.c
5+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:32:9-32:550)
6+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:34:9-34:33)
7+
[Info][Unsound] Unknown address given as function argument (12-loop-no-overflows.c:34:9-34:33)
8+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:20:5-20:45)
9+
[Warning][Imprecise][Program] Trying to read an index, but was not given an array ({
10+
next -> {&ldv_global_msg_list}
11+
prev -> {&ldv_global_msg_list}
12+
}) (12-loop-no-overflows.c:20:5-20:45)
13+
[Info][Unsound] Unknown address given as function argument (12-loop-no-overflows.c:20:5-20:45)
14+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:15:5-15:22)
15+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:16:5-16:22)
16+
[Info][Unsound] Unknown address given as function argument (12-loop-no-overflows.c:35:9-35:26)
17+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:24:5-24:20)
18+
[Warning][Behavior > Undefined > InvalidMemoryDeallocation][CWE-590] Points-to set for pointer msg->data in function free is top. Potentially invalid memory deallocation may occur (12-loop-no-overflows.c:24:5-24:20)
19+
[Warning][Behavior > Undefined > InvalidMemoryDeallocation][CWE-590] Points-to set for pointer msg in function free is top. Potentially invalid memory deallocation may occur (12-loop-no-overflows.c:25:5-25:14)
20+
[Warning][Behavior > Undefined > NullPointerDereference][CWE-476] May dereference NULL pointer (12-loop-no-overflows.c:32:444-32:470)
21+
[Info][Deadcode] Logical lines of code (LLoC) summary:
22+
live: 16
23+
dead: 0
24+
total lines: 16
25+

0 commit comments

Comments
 (0)