Skip to content

Commit

Permalink
Merge pull request #495 from goblint/escape-unknown
Browse files Browse the repository at this point in the history
Fix known addresses not escaping when address set contains unknown
  • Loading branch information
sim642 authored Dec 14, 2021
2 parents ed16687 + bb3e8eb commit 206f204
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
10 changes: 6 additions & 4 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -985,12 +985,14 @@ struct
match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local e with
| `Top -> Queries.Result.top q
| `Bot -> Queries.Result.bot q (* TODO: remove *)
| `Address a when AD.is_top a || AD.mem Addr.UnknownPtr a ->
Q.LS.top ()
| `Address a ->
let xs = List.map addrToLvalSet (reachable_vars (Analyses.ask_of_ctx ctx) [a] ctx.global ctx.local) in
let a' = AD.remove Addr.UnknownPtr a in (* run reachable_vars without unknown just to be safe *)
let xs = List.map addrToLvalSet (reachable_vars (Analyses.ask_of_ctx ctx) [a'] ctx.global ctx.local) in
let addrs = List.fold_left (Q.LS.join) (Q.LS.empty ()) xs in
addrs
if AD.mem Addr.UnknownPtr a then
Q.LS.add (dummyFunDec.svar, `NoOffset) addrs (* add unknown back *)
else
addrs
| _ -> Q.LS.empty ()
end
| Q.ReachableUkTypes e -> begin
Expand Down
2 changes: 1 addition & 1 deletion src/analyses/malloc_null.ml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct
match ask.f (Queries.ReachableFrom e) with
| a when not (Queries.LS.is_top a) ->
let to_extra (v,o) xs = AD.from_var_offset (v,(conv_offset o)) :: xs in
Queries.LS.fold to_extra a []
Queries.LS.fold to_extra (Queries.LS.remove (dummyFunDec.svar, `NoOffset) a) []
(* Ignore soundness warnings, as invalidation proper will raise them. *)
| _ -> []
in
Expand Down
7 changes: 5 additions & 2 deletions src/analyses/threadEscape.ml
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ struct
| a when not (Queries.LS.is_top a) ->
(* let to_extra (v,o) set = D.add (Addr.from_var_offset (v, cut_offset o)) set in *)
let to_extra (v,o) set = D.add v set in
Queries.LS.fold to_extra a (D.empty ())
Queries.LS.fold to_extra (Queries.LS.remove (dummyFunDec.svar, `NoOffset) a) (D.empty ())
(* Ignore soundness warnings, as invalidation proper will raise them. *)
| _ -> D.empty ()
| a ->
if M.tracing then M.tracel "escape" "reachable %a: %a\n" d_exp e Queries.LS.pretty a;
D.empty ()

let special ctx (lval: lval option) (f:varinfo) (arglist:exp list) : D.t =
ctx.local
Expand All @@ -84,6 +86,7 @@ struct
match args with
| [ptc_arg] ->
let escaped = fctx.local in (* reuse reachable computation from threadenter *)
if M.tracing then M.tracel "escape" "%a: %a\n" d_exp ptc_arg D.pretty escaped;
if not (D.is_empty escaped) then (* avoid emitting unnecessary event *)
ctx.emit (Events.Escape escaped);
escaped
Expand Down
4 changes: 2 additions & 2 deletions src/analyses/uninit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct
match ask (Queries.ReachableFrom e) with
| a when not (Queries.LS.is_top a) ->
let to_extra (v,o) xs = (v, Base.Offs.from_offset (conv_offset o), true) :: xs in
Queries.LS.fold to_extra a []
Queries.LS.fold to_extra (Queries.LS.remove (dummyFunDec.svar, `NoOffset) a) []
(* Ignore soundness warnings, as invalidation proper will raise them. *)
| _ -> []
in
Expand Down Expand Up @@ -227,7 +227,7 @@ struct
match ask.f (Queries.ReachableFrom e) with
| a when not (Queries.LS.is_top a) ->
let to_extra (v,o) xs = AD.from_var_offset (v,(conv_offset o)) :: xs in
Queries.LS.fold to_extra a []
Queries.LS.fold to_extra (Queries.LS.remove (dummyFunDec.svar, `NoOffset) a) []
(* Ignore soundness warnings, as invalidation proper will raise them. *)
| _ -> []
in
Expand Down
28 changes: 28 additions & 0 deletions tests/regression/02-base/70-escape-unknown.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <pthread.h>
#include <assert.h>

int *p;

void *t_fun(void *arg) {
if (arg != NULL) {
*((int*)arg) = 42;
}
return NULL;
}

int main() {
pthread_t id, id2;
int *r; // unknown
int i = 5;

pthread_create(&id, NULL, t_fun, NULL); // enter multithreaded

p = r;
p = &i;

pthread_create(&id2, NULL, t_fun, p); // i should escape, even if p contains unknown

assert(i == 5); // UNKNOWN!

return 0;
}

0 comments on commit 206f204

Please sign in to comment.