Skip to content

Commit

Permalink
Merge pull request #1508 from goblint/issue_1507
Browse files Browse the repository at this point in the history
Introduce sync reason `JoinCall` & Limit `sync` at function start nodes
  • Loading branch information
michael-schwarz authored Jun 13, 2024
2 parents b016c54 + eec5f2c commit c8dcdaa
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/analyses/apron/relationAnalysis.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ struct
PCU.RH.replace results ctx.node new_value;
end;
WideningTokens.with_local_side_tokens (fun () ->
Priv.sync (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg ctx.local (reason :> [`Normal | `Join | `Return | `Init | `Thread])
Priv.sync (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg ctx.local (reason :> [`Normal | `Join | `JoinCall | `Return | `Init | `Thread])
)

let init marshal =
Expand Down
80 changes: 52 additions & 28 deletions src/analyses/apron/relationPriv.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module type S =
val lock: Q.ask -> (V.t -> G.t) -> relation_components_t -> LockDomain.Addr.t -> relation_components_t
val unlock: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> relation_components_t -> LockDomain.Addr.t -> relation_components_t

val sync: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> relation_components_t -> [`Normal | `Join | `Return | `Init | `Thread] -> relation_components_t
val sync: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> relation_components_t -> [`Normal | `Join | `JoinCall | `Return | `Init | `Thread] -> relation_components_t

val escape: Node.t -> Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> relation_components_t -> EscapeDomain.EscapedVars.t -> relation_components_t
val enter_multithreaded: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> relation_components_t -> relation_components_t
Expand Down Expand Up @@ -96,8 +96,7 @@ struct
{ st with rel = rel_local }

let sync (ask: Q.ask) getg sideg (st: relation_components_t) reason =
match reason with
| `Join when ConfCheck.branched_thread_creation () ->
let branched_sync () =
if ask.f (Q.MustBeSingleThreaded {since_start = true}) then
st
else
Expand All @@ -110,7 +109,14 @@ struct
)
in
{st with rel = rel_local}
in
match reason with
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `Join
| `JoinCall
| `Normal
| `Init
| `Thread
Expand Down Expand Up @@ -337,17 +343,8 @@ struct
let thread_join ?(force=false) ask getg exp st = st
let thread_return ask getg sideg tid st = st

let sync ask getg sideg (st: relation_components_t) reason =
match reason with
| `Return -> (* required for thread return *)
(* TODO: implement? *)
begin match ThreadId.get_current ask with
| `Lifted x (* when CPA.mem x st.cpa *) ->
st
| _ ->
st
end
| `Join when ConfCheck.branched_thread_creation () ->
let sync (ask:Q.ask) getg sideg (st: relation_components_t) reason =
let branched_sync () =
if ask.f (Q.MustBeSingleThreaded { since_start= true }) then
st
else
Expand Down Expand Up @@ -376,7 +373,22 @@ struct
let rel_local' = RD.meet rel_local (getg ()) in
{st with rel = rel_local'} *)
st
in
match reason with
| `Return -> (* required for thread return *)
(* TODO: implement? *)
begin match ThreadId.get_current ask with
| `Lifted x (* when CPA.mem x st.cpa *) ->
st
| _ ->
st
end
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Normal
| `Init
| `Thread ->
Expand Down Expand Up @@ -626,17 +638,8 @@ struct
let thread_join ?(force=false) ask getg exp st = st
let thread_return ask getg sideg tid st = st

let sync ask getg sideg (st: relation_components_t) reason =
match reason with
| `Return -> (* required for thread return *)
(* TODO: implement? *)
begin match ThreadId.get_current ask with
| `Lifted x (* when CPA.mem x st.cpa *) ->
st
| _ ->
st
end
| `Join when ConfCheck.branched_thread_creation () ->
let sync (ask:Q.ask) getg sideg (st: relation_components_t) reason =
let branched_sync () =
if ask.f (Q.MustBeSingleThreaded {since_start = true}) then
st
else
Expand All @@ -659,7 +662,22 @@ struct
)
in
{st with rel = rel_local}
in
match reason with
| `Return -> (* required for thread return *)
(* TODO: implement? *)
begin match ThreadId.get_current ask with
| `Lifted x (* when CPA.mem x st.cpa *) ->
st
| _ ->
st
end
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Normal
| `Init
| `Thread ->
Expand Down Expand Up @@ -1192,9 +1210,7 @@ struct
st

let sync (ask:Q.ask) getg sideg (st: relation_components_t) reason =
match reason with
| `Return -> st (* TODO: implement? *)
| `Join when ConfCheck.branched_thread_creation () ->
let branched_sync () =
if ask.f (Q.MustBeSingleThreaded {since_start = true}) then
st
else
Expand All @@ -1209,7 +1225,15 @@ struct
)
in
{st with rel = rel_local}
in
match reason with
| `Return -> st (* TODO: implement? *)
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Normal
| `Init
| `Thread ->
Expand Down
2 changes: 1 addition & 1 deletion src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ struct
else
ctx.local

let sync ctx reason = sync' (reason :> [`Normal | `Join | `Return | `Init | `Thread]) ctx
let sync ctx reason = sync' (reason :> [`Normal | `Join | `JoinCall | `Return | `Init | `Thread]) ctx

let publish_all ctx reason =
ignore (sync' reason ctx)
Expand Down
43 changes: 35 additions & 8 deletions src/analyses/basePriv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ sig
val lock: Q.ask -> (V.t -> G.t) -> BaseComponents (D).t -> LockDomain.Addr.t -> BaseComponents (D).t
val unlock: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseComponents (D).t -> LockDomain.Addr.t -> BaseComponents (D).t

val sync: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseComponents (D).t -> [`Normal | `Join | `Return | `Init | `Thread] -> BaseComponents (D).t
val sync: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseComponents (D).t -> [`Normal | `Join | `JoinCall | `Return | `Init | `Thread] -> BaseComponents (D).t

val escape: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseComponents (D).t -> EscapeDomain.EscapedVars.t -> BaseComponents (D).t
val enter_multithreaded: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseComponents (D).t -> BaseComponents (D).t
Expand Down Expand Up @@ -306,8 +306,8 @@ struct
st

let sync ask getg sideg (st: BaseComponents (D).t) reason =
match reason with
| `Join when ConfCheck.branched_thread_creation () -> (* required for branched thread creation *)
let branched_sync () =
(* required for branched thread creation *)
let global_cpa = CPA.filter (fun x _ -> is_global ask x && is_unprotected ask x) st.cpa in
sideg V.mutex_inits global_cpa; (* must be like enter_multithreaded *)
(* TODO: this makes mutex-oplus less precise in 28-race_reach/10-ptrmunge_racefree and 28-race_reach/trylock2_racefree, why? *)
Expand All @@ -318,7 +318,14 @@ struct
sideg (V.global x) (CPA.singleton x v)
) st.cpa;
st
in
match reason with
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Return
| `Normal
| `Init
Expand Down Expand Up @@ -404,8 +411,8 @@ struct
{st with cpa = cpa'}

let sync ask getg sideg (st: BaseComponents (D).t) reason =
match reason with
| `Join when ConfCheck.branched_thread_creation () -> (* required for branched thread creation *)
let branched_sync () =
(* required for branched thread creation *)
let global_cpa = CPA.filter (fun x _ -> is_global ask x && is_unprotected ask x) st.cpa in
sideg V.mutex_inits global_cpa; (* must be like enter_multithreaded *)

Expand All @@ -422,7 +429,14 @@ struct
) st.cpa st.cpa
in
{st with cpa = cpa'}
in
match reason with
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Return
| `Normal
| `Init
Expand Down Expand Up @@ -772,9 +786,9 @@ struct
) st.cpa st

let sync ask getg sideg (st: BaseComponents (D).t) reason =
let sideg = Wrapper.sideg ask sideg in
match reason with
| `Join when ConfCheck.branched_thread_creation () -> (* required for branched thread creation *)
let branched_sync () =
(* required for branched thread creation *)
let sideg = Wrapper.sideg ask sideg in
CPA.fold (fun x v (st: BaseComponents (D).t) ->
if is_global ask x && is_unprotected ask x then (
sideg (V.unprotected x) v;
Expand All @@ -784,7 +798,14 @@ struct
else
st
) st.cpa st
in
match reason with
| `Join when ConfCheck.branched_thread_creation () ->
branched_sync ()
| `JoinCall when ConfCheck.branched_thread_creation_at_call ask ->
branched_sync ()
| `Join
| `JoinCall
| `Return
| `Normal
| `Init
Expand Down Expand Up @@ -1034,6 +1055,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down Expand Up @@ -1089,6 +1111,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down Expand Up @@ -1160,6 +1183,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down Expand Up @@ -1318,6 +1342,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down Expand Up @@ -1496,6 +1521,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down Expand Up @@ -1678,6 +1704,7 @@ struct
| `Return
| `Normal
| `Join (* TODO: no problem with branched thread creation here? *)
| `JoinCall
| `Init
| `Thread ->
st
Expand Down
2 changes: 1 addition & 1 deletion src/analyses/basePriv.mli
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ sig
val lock: Queries.ask -> (V.t -> G.t) -> BaseDomain.BaseComponents (D).t -> LockDomain.Addr.t -> BaseDomain.BaseComponents (D).t
val unlock: Queries.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseDomain.BaseComponents (D).t -> LockDomain.Addr.t -> BaseDomain.BaseComponents (D).t

val sync: Queries.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseDomain.BaseComponents (D).t -> [`Normal | `Join | `Return | `Init | `Thread] -> BaseDomain.BaseComponents (D).t
val sync: Queries.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseDomain.BaseComponents (D).t -> [`Normal | `Join | `JoinCall | `Return | `Init | `Thread] -> BaseDomain.BaseComponents (D).t

val escape: Queries.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseDomain.BaseComponents (D).t -> EscapeDomain.EscapedVars.t -> BaseDomain.BaseComponents (D).t
val enter_multithreaded: Queries.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> BaseDomain.BaseComponents (D).t -> BaseDomain.BaseComponents (D).t
Expand Down
18 changes: 18 additions & 0 deletions src/analyses/commonPriv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ struct
not threadflag_path_sens
else
true

(** Whether branched thread creation at start nodes of procedures needs to be handled by [sync `JoinCall] of privatization. *)
let branched_thread_creation_at_call (ask:Queries.ask) =
let threadflag_active = List.mem "threadflag" (GobConfig.get_string_list "ana.activated") in
if threadflag_active then
let sens = GobConfig.get_string_list "ana.ctx_sens" in
let threadflag_ctx_sens = match sens with
| [] -> (* use values of "ana.ctx_insens" (blacklist) *)
not (List.mem "threadflag" @@ GobConfig.get_string_list "ana.ctx_insens")
| sens -> (* use values of "ana.ctx_sens" (whitelist) *)
List.mem "threadflag" sens
in
if not threadflag_ctx_sens then
true
else
ask.f (Queries.GasExhausted)
else
true
end

module Protection =
Expand Down
7 changes: 7 additions & 0 deletions src/analyses/mCP.ml
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,13 @@ struct
f (Result.top ()) (!base_id, spec !base_id, assoc !base_id ctx.local) *)
| Queries.DYojson ->
`Lifted (D.to_yojson ctx.local)
| Queries.GasExhausted ->
if (get_int "ana.context.gas_value" >= 0) then
(* There is a lifter above this that will answer it, save to ask *)
ctx.ask (Queries.GasExhausted)
else
(* Abort to avoid infinite recursion *)
false
| _ ->
let r = fold_left (f ~q) (Result.top ()) @@ spec_list ctx.local in
do_sideg ctx !sides;
Expand Down
2 changes: 1 addition & 1 deletion src/config/options.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@
},
"gas_value": {
"title": "ana.context.gas_value",
"description": "Denotes the gas value x for the ContextGasLifter. Negative values deactivate the context gas, zero yields a context-insensitve analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitively. Any calls deeper in the call stack are analyzed with the same (empty) context.",
"description": "Denotes the gas value x for the ContextGasLifter. Negative values deactivate the context gas, zero yields a context-insensitive analysis. If enabled, the first x recursive calls of the call stack are analyzed context-sensitively. Any calls deeper in the call stack are analyzed with the same (empty) context.",
"type": "integer",
"default": -1
},
Expand Down
5 changes: 5 additions & 0 deletions src/domains/queries.ml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type _ t =
| IsEverMultiThreaded: MayBool.t t
| TmpSpecial: Mval.Exp.t -> ML.t t
| MaySignedOverflow: exp -> MayBool.t t
| GasExhausted: MustBool.t t

type 'a result = 'a

Expand Down Expand Up @@ -196,6 +197,7 @@ struct
| IsEverMultiThreaded -> (module MayBool)
| TmpSpecial _ -> (module ML)
| MaySignedOverflow _ -> (module MayBool)
| GasExhausted -> (module MustBool)

(** Get bottom result for query. *)
let bot (type a) (q: a t): a result =
Expand Down Expand Up @@ -265,6 +267,7 @@ struct
| IsEverMultiThreaded -> MayBool.top ()
| TmpSpecial _ -> ML.top ()
| MaySignedOverflow _ -> MayBool.top ()
| GasExhausted -> MustBool.top ()
end

(* The type any_query can't be directly defined in Any as t,
Expand Down Expand Up @@ -331,6 +334,7 @@ struct
| Any (TmpSpecial _) -> 56
| Any (IsAllocVar _) -> 57
| Any (MaySignedOverflow _) -> 58
| Any GasExhausted -> 59

let rec compare a b =
let r = Stdlib.compare (order a) (order b) in
Expand Down Expand Up @@ -490,6 +494,7 @@ struct
| Any IsEverMultiThreaded -> Pretty.dprintf "IsEverMultiThreaded"
| Any (TmpSpecial lv) -> Pretty.dprintf "TmpSpecial %a" Mval.Exp.pretty lv
| Any (MaySignedOverflow e) -> Pretty.dprintf "MaySignedOverflow %a" CilType.Exp.pretty e
| Any GasExhausted -> Pretty.dprintf "GasExhausted"
end

let to_value_domain_ask (ask: ask) =
Expand Down
Loading

0 comments on commit c8dcdaa

Please sign in to comment.