Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce sync reason JoinCall & Limit sync at function start nodes #1508

Merged
merged 4 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading