Skip to content

Commit 138a482

Browse files
authored
Merge pull request #1176 from goblint/race-null
Fix `NULL` and unknown pointer handling in `MayPointTo` and `ReachableFrom` for race analysis
2 parents 631888e + 204594e commit 138a482

File tree

5 files changed

+231
-1
lines changed

5 files changed

+231
-1
lines changed

src/analyses/base.ml

+12-1
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,7 @@ struct
12701270
match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local e with
12711271
| Address a -> a
12721272
| Bot -> Queries.Result.bot q (* TODO: remove *)
1273+
| Int i -> AD.of_int i
12731274
| _ -> Queries.Result.top q
12741275
end
12751276
| Q.EvalThread e -> begin
@@ -1287,7 +1288,17 @@ struct
12871288
| Address a ->
12881289
let a' = AD.remove Addr.UnknownPtr a in (* run reachable_vars without unknown just to be safe: TODO why? *)
12891290
let addrs = reachable_vars (Analyses.ask_of_ctx ctx) [a'] ctx.global ctx.local in
1290-
List.fold_left (AD.join) (AD.empty ()) addrs
1291+
let addrs' = List.fold_left (AD.join) (AD.empty ()) addrs in
1292+
if AD.may_be_unknown a then
1293+
AD.add UnknownPtr addrs' (* add unknown back *)
1294+
else
1295+
addrs'
1296+
| Int i ->
1297+
begin match Cilfacade.typeOf e with
1298+
| t when Cil.isPointerType t -> AD.of_int i (* integer used as pointer *)
1299+
| _
1300+
| exception Cilfacade.TypeOfError _ -> AD.empty () (* avoid unknown pointer result for non-pointer expression *)
1301+
end
12911302
| _ -> AD.empty ()
12921303
end
12931304
| Q.ReachableUkTypes e -> begin
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <pthread.h>
2+
#include <stdio.h>
3+
4+
void *t_fun(void *arg) {
5+
void **top;
6+
free(top); // RACE
7+
return NULL;
8+
}
9+
10+
int main(void) {
11+
pthread_t id;
12+
pthread_create(&id, NULL, t_fun, NULL);
13+
14+
int r; // rand
15+
int zero = 0; // IntDomain zero
16+
void *null;
17+
__goblint_assume(null == NULL); // AddressDomain NULL
18+
int one = 1; // IntDomain one
19+
void *unknown;
20+
__goblint_assume(unknown != NULL); // AddressDomain unknown
21+
void *top;
22+
switch (r) {
23+
case 0:
24+
pthread_join(id, NULL); // NORACE
25+
break;
26+
case 1:
27+
pthread_join(id, 0); // NORACE
28+
break;
29+
case 2:
30+
pthread_join(id, zero); // NORACE
31+
break;
32+
case 3:
33+
pthread_join(id, 1); // RACE
34+
break;
35+
case 4:
36+
pthread_join(id, one); // RACE
37+
break;
38+
case 5:
39+
pthread_join(id, r); // RACE
40+
break;
41+
case 6:
42+
pthread_join(id, null); // NORACE
43+
break;
44+
case 7:
45+
pthread_join(id, unknown); // RACE
46+
break;
47+
case 8:
48+
pthread_join(id, top); // RACE
49+
break;
50+
default:
51+
break;
52+
}
53+
return 0;
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// PARAM: --enable ana.race.direct-arithmetic
2+
#include <pthread.h>
3+
#include <stdio.h>
4+
5+
void *t_fun(void *arg) {
6+
void *top;
7+
time(top); // RACE
8+
return NULL;
9+
}
10+
11+
int main(void) {
12+
pthread_t id;
13+
pthread_create(&id, NULL, t_fun, NULL);
14+
15+
int r; // rand
16+
int zero = 0; // IntDomain zero
17+
void *null;
18+
__goblint_assume(null == NULL); // AddressDomain NULL
19+
int one = 1; // IntDomain one
20+
void *unknown;
21+
__goblint_assume(unknown != NULL); // AddressDomain unknown
22+
void *top;
23+
switch (r) {
24+
case 0:
25+
time(NULL); // NORACE
26+
break;
27+
case 1:
28+
time(0); // NORACE
29+
break;
30+
case 2:
31+
time(zero); // NORACE
32+
break;
33+
case 3:
34+
time(1); // RACE
35+
break;
36+
case 4:
37+
time(one); // RACE
38+
break;
39+
case 5:
40+
time(r); // RACE
41+
break;
42+
case 6:
43+
time(null); // NORACE
44+
break;
45+
case 7:
46+
time(unknown); // RACE
47+
break;
48+
case 8:
49+
time(top); // RACE
50+
break;
51+
default:
52+
break;
53+
}
54+
return 0;
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include <pthread.h>
2+
#include <stdio.h>
3+
4+
pthread_key_t key;
5+
6+
void *t_fun(void *arg) {
7+
void *top;
8+
pthread_setspecific(key, top); // RACE
9+
return NULL;
10+
}
11+
12+
int main(void) {
13+
pthread_t id;
14+
pthread_create(&id, NULL, t_fun, NULL);
15+
16+
int r; // rand
17+
int zero = 0; // IntDomain zero
18+
void *null;
19+
__goblint_assume(null == NULL); // AddressDomain NULL
20+
int one = 1; // IntDomain one
21+
void *unknown;
22+
__goblint_assume(unknown != NULL); // AddressDomain unknown
23+
void *top;
24+
switch (r) {
25+
case 0:
26+
pthread_setspecific(key, NULL); // NORACE
27+
break;
28+
case 1:
29+
pthread_setspecific(key, 0); // NORACE
30+
break;
31+
case 2:
32+
pthread_setspecific(key, zero); // NORACE
33+
break;
34+
case 3:
35+
pthread_setspecific(key, 1); // RACE
36+
break;
37+
case 4:
38+
pthread_setspecific(key, one); // RACE
39+
break;
40+
case 5:
41+
pthread_setspecific(key, r); // RACE
42+
break;
43+
case 6:
44+
pthread_setspecific(key, null); // NORACE
45+
break;
46+
case 7:
47+
pthread_setspecific(key, unknown); // RACE
48+
break;
49+
case 8:
50+
pthread_setspecific(key, top); // RACE
51+
break;
52+
default:
53+
break;
54+
}
55+
return 0;
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <pthread.h>
2+
#include <stdio.h>
3+
4+
void *t_fun(void *arg) {
5+
void *top;
6+
fclose(top); // RACE
7+
return NULL;
8+
}
9+
10+
int main(void) {
11+
pthread_t id;
12+
pthread_create(&id, NULL, t_fun, NULL);
13+
14+
int r; // rand
15+
int zero = 0; // IntDomain zero
16+
void *null;
17+
__goblint_assume(null == NULL); // AddressDomain NULL
18+
int one = 1; // IntDomain one
19+
void *unknown;
20+
__goblint_assume(unknown != NULL); // AddressDomain unknown
21+
void *top;
22+
switch (r) {
23+
case 0:
24+
feof(NULL); // NORACE
25+
break;
26+
case 1:
27+
feof(0); // NORACE
28+
break;
29+
case 2:
30+
feof(zero); // NORACE
31+
break;
32+
case 3:
33+
feof(1); // RACE
34+
break;
35+
case 4:
36+
feof(one); // RACE
37+
break;
38+
case 5:
39+
feof(r); // RACE
40+
break;
41+
case 6:
42+
feof(null); // NORACE
43+
break;
44+
case 7:
45+
feof(unknown); // RACE
46+
break;
47+
case 8:
48+
feof(top); // RACE
49+
break;
50+
default:
51+
break;
52+
}
53+
return 0;
54+
}

0 commit comments

Comments
 (0)