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

Generate flow-insensitive YAML witness invariants with ghosts for privatized variables #1394

Merged
merged 115 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
9ee9ce7
Add reach_error to library functions
sim642 Mar 13, 2024
4752ddf
Make some YAML witness validation messages more severe
sim642 Mar 13, 2024
2e22af7
Add ghost_variable and ghost_update to YAML witness types
sim642 Mar 13, 2024
688c4dc
Add mutexGhosts analysis
sim642 Mar 13, 2024
45be164
Add YamlEntryGlobal query
sim642 Mar 13, 2024
5d3f5fe
Generate YAML witness ghosts for mutexes
sim642 Mar 13, 2024
a80242a
Make protection privatization more precise with earlyglobs
sim642 Mar 14, 2024
086e60d
Add ask argument to BasePriv invariant_global-s
sim642 Mar 14, 2024
b2d09da
Add MustProtectingLocks query
sim642 Mar 14, 2024
526d88a
Generate protected flow-insensitive invariants with ghosts
sim642 Mar 14, 2024
d536db4
Make mutex ghost variable names distinct from mutex variables
sim642 Mar 14, 2024
2eafa69
Document MutexGhosts
sim642 Mar 14, 2024
470ddbc
Fix coverage build
sim642 Mar 14, 2024
0d5ef63
Make mutex-meet privatization more precise with earlyglobs
sim642 Mar 14, 2024
a714dc6
Generate mutex-meet flow-insensitive invariants with ghosts
sim642 Mar 14, 2024
652aeae
Add ghost variable for multithreaded mode
sim642 Mar 14, 2024
7c33c72
Reorder disjuncts in privatized invariants in implication order
sim642 Mar 14, 2024
4381e9f
Fix MustProtectingLocks query crash with top
sim642 Mar 14, 2024
60a51b9
Fix protection privatization protected invariant with no protecting m…
sim642 Mar 14, 2024
fd84cd9
Fix mutex-meet privatization protected invariant with no protecting m…
sim642 Mar 14, 2024
516e3ad
Use RichVarinfo for witness ghost variables
sim642 Mar 15, 2024
a10c973
Deduplicate witness ghost entry creation
sim642 Mar 15, 2024
932ac3b
Allow non-void types for RichVarinfo
sim642 Mar 15, 2024
7951588
Merge branch 'yaml-witness-test' into yaml-witness-ghost
sim642 Apr 2, 2024
b018265
Add cram test for privatized witness ghosts
sim642 Apr 2, 2024
7992462
Add cram test for witness ghosts with multiple protecting locks
sim642 Apr 2, 2024
01c9b98
mutex-meet ghost invariants are maybe unsound
sim642 Apr 2, 2024
a07e890
Merge branch 'master' into yaml-witness-ghost
sim642 Apr 4, 2024
d3a5a0a
Add NOWARNs to commented out checks in 56-witness/64-ghost-multiple-p…
sim642 Apr 4, 2024
612c1cc
Remove TODO about mutex-meet unsound witness invariants
sim642 Apr 15, 2024
ff0d6a5
Merge branch 'master' into yaml-witness-ghost
sim642 Apr 15, 2024
e235ba7
Rewrite mutexGhosts with may locksets per node
sim642 Apr 15, 2024
726f646
Add test for mutex ghosts for alloc variables
sim642 Apr 15, 2024
3e9d7c3
Add valid names to alloc mutex ghosts
sim642 Apr 15, 2024
b19cc2d
Fix mutexGhosts indentation
sim642 Apr 16, 2024
885d0cf
Use non-recursive mutex in 56-witness/66-ghost-alloc-lock
sim642 Apr 16, 2024
21ae83a
Fix mutexGhosts unlocking everything at function return
sim642 Apr 16, 2024
d67c083
Revert "Rewrite mutexGhosts with may locksets per node"
sim642 Apr 18, 2024
c472adf
Add lock global unknowns to mutexGhosts
sim642 Apr 18, 2024
fd64898
Add PARAM to 56-witness/64-ghost-multiple-protecting
sim642 Apr 19, 2024
e3ded4e
Find ambiguous mutexes in mutexGhosts
sim642 Apr 19, 2024
b96f8a2
Avoid emitting witness ghosts for ambiguous mutexes
sim642 Apr 19, 2024
c6f12a6
Move LockDomain.Symbolic to SymbLocksDomain
sim642 Apr 19, 2024
8985d64
Extract WitnessGhostVar to break dependency cycle
sim642 Apr 19, 2024
b04af51
Refactor GhostVarAvailable query
sim642 Apr 19, 2024
d8bd13d
Exclude WitnessGhostVar from docs check
sim642 Apr 19, 2024
6750c7c
Merge branch 'master' into yaml-witness-ghost
sim642 Apr 22, 2024
947d6bc
Fix __VERIFIER_atomic special mutex ghost varialbe name
sim642 Apr 23, 2024
4ada6eb
Avoid emitting useless protected invariants from protection privatiza…
sim642 Apr 23, 2024
a7d43a9
Avoid useless work in mutex-meet invariant_global if ghost variable i…
sim642 Apr 23, 2024
d6abc0b
Fix struct field mutex ghost variable name
sim642 Apr 23, 2024
6db1d04
Fix definite array index mutex ghost variable name
sim642 Apr 23, 2024
53a714f
Make non-definite ghost variables unavailable
sim642 Apr 23, 2024
413b2e1
Disable mutex ghosts with indices
sim642 Apr 23, 2024
ea849fb
Detect thread create nodes in mutexGhosts
sim642 Apr 24, 2024
594beac
Refactor mutexGhosts thread creation collection
sim642 Apr 24, 2024
584b788
Add option to emit flow_insensitive_invariant-s as location_invariant-s
sim642 Apr 24, 2024
8d5cc12
Add svcomp-ghost conf
sim642 Apr 25, 2024
96d862e
Use YAML witness format-version 0.1 for svcomp-ghost
sim642 Apr 25, 2024
257fa8c
Test witness.invariant.flow_insensitive-as-location with for loop
sim642 Apr 25, 2024
10dfba1
Fix witness.invariant.flow_insensitive-as-location at loop node
sim642 Apr 25, 2024
16c97fd
Add cram test for relational mutex-meet flow-insensitive invariants
sim642 Apr 30, 2024
5650784
Add InvariantGlobal interface to relational privatizations
sim642 Apr 30, 2024
d3565cb
Implement relational mutex-meet flow-insensitive invariants
sim642 Apr 30, 2024
1aa35d8
Filter relational mutex-meet ghost invariant with keep_only_protected…
sim642 Apr 30, 2024
c4a8936
Add filters to relational InvariantGlobal
sim642 Apr 30, 2024
535de76
Add test with __VERIFIER_atomic_locked ghost variable
sim642 May 7, 2024
6f3b6fb
Treat __VERIFIER_atomic_locked as false in witnesses
sim642 May 7, 2024
2e26aab
Merge branch 'master' into yaml-witness-ghost
sim642 May 7, 2024
2e6673f
Disable 13-privatized/04-priv_multi cram test on OSX
sim642 May 8, 2024
b7582a4
Make 36-apron/12-traces-min-rpb1 cram test warnings deterministic
sim642 May 8, 2024
cad5f6e
Add BasePriv invariant_global tracing
sim642 May 20, 2024
bd329e1
Fix mutex-meet invariant_global not including MUTEX_INITS
sim642 May 21, 2024
2a79e42
Add comment about multiple protecting mutexes for ghost invariants
sim642 Jun 4, 2024
e6bf34d
Merge branch 'master' into yaml-witness-ghost
sim642 Jun 4, 2024
2e42c7b
Add ghost_variable and ghost_update YAML entry types to option
sim642 Jun 5, 2024
e7931ff
Make InvariantGlobalNodes query lazy in YAML witness generation
sim642 Jun 5, 2024
36ff621
Fix comment about YamlEntryGlobal
sim642 Jun 5, 2024
7fcb10c
Handle pthread_rwlock_t as opaque mutex in base analysis
sim642 Jun 18, 2024
1570adb
Merge branch 'master' into yaml-witness-ghost
sim642 Jul 31, 2024
c18061e
Remove pthreadMutexType from ghost witness tests
sim642 Jul 31, 2024
6055e8d
Activate abortUnless in svcomp-ghost conf also
sim642 Jul 31, 2024
6e79314
Update TODO comment about base earlyglobs flow-insensitive invariants
sim642 Jul 31, 2024
13333f5
Merge branch 'master' into yaml-witness-ghost
sim642 Aug 7, 2024
d937d68
Add options ana.base.invariant.local and ana.base.invariant.global
sim642 Aug 7, 2024
fbc9e62
Add option ana.var_eq.invariant.enabled
sim642 Aug 7, 2024
58aaf53
Update svcomp-ghost conf
sim642 Aug 7, 2024
641d447
Merge branch 'master' into yaml-witness-ghost
sim642 Aug 7, 2024
f20ed62
Re-enable witness.invariant.{loop-head,other} in svcomp-ghost conf fo…
sim642 Aug 8, 2024
342ed74
Merge branch 'master' into yaml-witness-ghost
sim642 Aug 20, 2024
9c60418
Add YAML witness ghost_instrumentation entry type
sim642 Aug 20, 2024
d220653
Add ghost_instrumentation support to mutexGhosts
sim642 Aug 20, 2024
f79ad18
Add option for emitting flow_insensitive_invariant-s as invariant_set…
sim642 Aug 20, 2024
e9e652d
Use invariant_set in svcomp-ghost conf
sim642 Aug 20, 2024
431b34d
Make invariant_set and ghost_instrumentation deterministic in tests
sim642 Aug 20, 2024
2c99550
Remove ghost_ prefix from ghost_instrumentation update entries
sim642 Aug 28, 2024
12dadf4
Wrap ghost_instrumentation in content
sim642 Sep 2, 2024
852297b
Add value and format to ghost_instrumentation
sim642 Sep 2, 2024
ced56ca
Document YamlEntryGlobal and InvariantGlobalNodes queries
sim642 Nov 21, 2024
969b87a
Replace privatization invariant_global mutex_inits TODO with comment
sim642 Nov 21, 2024
4940658
Apply suggestions from code review
sim642 Nov 21, 2024
09045bc
Add nontrivial condition for querying YamlEntryGlobal at all
sim642 Nov 21, 2024
3a07c16
Remove old unnecessary branching from ghost_update YAML witness entries
sim642 Nov 21, 2024
9a3a338
Implement YamlWitnessType.Entry pretty-printing
sim642 Nov 21, 2024
34277e0
Use sets instead of BatList.mem_cmp for deduplicating ghost witness v…
sim642 Nov 21, 2024
7929d63
Extract fold_flow_insensitive_as_location in YamlWitness to deduplica…
sim642 Nov 21, 2024
8a0240d
Update ghost witness related TODOs and comments
sim642 Nov 21, 2024
002fdd3
Merge branch 'master' into yaml-witness-ghost
sim642 Nov 21, 2024
64c11c2
Add test 56-witness/69-ghost-ptr-protection for unsound protection fl…
sim642 Nov 21, 2024
b4734c3
Fix unsound ghost witness invariant in 56-witness/69-ghost-ptr-protec…
sim642 Nov 21, 2024
d2e71cb
Change ghost witness tests to use ghost_instrumentation
sim642 Nov 21, 2024
554bd7f
Avoid empty ghost_instrumentation location updates
sim642 Nov 21, 2024
2c25848
Remove support for old ghost_variable and ghost_update entry types
sim642 Nov 21, 2024
3369955
Merge branch 'master' into yaml-witness-ghost
sim642 Nov 29, 2024
ffe255b
Count witness.invariant.flow_insensitive-as location invariants in su…
sim642 Nov 29, 2024
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
139 changes: 139 additions & 0 deletions conf/svcomp-ghost.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
{
"ana": {
"sv-comp": {
"enabled": true,
"functions": true
},
"int": {
"def_exc": true,
"enums": false,
"interval": true
},
"float": {
"interval": true,
"evaluate_math_functions": true
},
"activated": [
"base",
"threadid",
"threadflag",
"threadreturn",
"mallocWrapper",
"mutexEvents",
"mutex",
"access",
"race",
"escape",
"expRelation",
"mhp",
"assert",
"var_eq",
"symb_locks",
"region",
"thread",
"threadJoins",
"abortUnless",
"mutexGhosts",
"pthreadMutexType"
],
"path_sens": [
"mutex",
"malloc_null",
"uninit",
"expsplit",
"activeSetjmp",
"memLeak",
"threadflag"
],
"context": {
"widen": false
},
"base": {
"arrays": {
"domain": "partitioned"
},
"invariant": {
"local": false,
"global": true
}
},
"relation": {
"invariant": {
"local": false,
"global": true,
"one-var": false
}
},
"apron": {
"invariant": {
"diff-box": true
}
},
"var_eq": {
"invariant": {
"enabled": false
}
},
"race": {
"free": false,
"call": false
},
"autotune": {
"enabled": true,
"activated": [
"singleThreaded",
"mallocWrappers",
"noRecursiveIntervals",
"enums",
"congruence",
"octagon",
"wideningThresholds",
"loopUnrollHeuristic",
"memsafetySpecification",
"noOverflows",
"termination",
"tmpSpecialAnalysis"
]
}
},
"exp": {
"region-offsets": true
},
"solver": "td3",
"sem": {
"unknown_function": {
"spawn": false
},
"int": {
"signed_overflow": "assume_none"
},
"null-pointer": {
"dereference": "assume_none"
}
},
"witness": {
"graphml": {
"enabled": false
},
"yaml": {
"enabled": true,
"format-version": "2.1",
"entry-types": [
"flow_insensitive_invariant",
"ghost_instrumentation"
]
},
"invariant": {
"loop-head": true,
"after-lock": true,
"other": true,
"accessed": false,
"exact": true,
"all-locals": false,
"flow_insensitive-as": "invariant_set-location_invariant"
}
},
"pre": {
"enabled": false
}
}
1 change: 1 addition & 0 deletions scripts/goblint-lib-modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

"MessageCategory", # included in Messages
"PreValueDomain", # included in ValueDomain
"WitnessGhostVar", # included in WitnessGhost

"ConfigVersion",
"ConfigProfile",
Expand Down
12 changes: 12 additions & 0 deletions src/analyses/apron/relationAnalysis.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,15 @@ struct
)
|> Enum.fold (fun acc x -> Invariant.(acc && of_exp x)) Invariant.none

let query_invariant_global ctx g =
if GobConfig.get_bool "ana.relation.invariant.global" && ctx.ask (GhostVarAvailable Multithreaded) then (
let var = WitnessGhost.to_varinfo Multithreaded in
let inv = Priv.invariant_global (Analyses.ask_of_ctx ctx) ctx.global g in
Invariant.(of_exp (UnOp (LNot, Lval (GoblintCil.var var), GoblintCil.intType)) || inv) [@coverage off] (* bisect_ppx cannot handle redefined (||) *)
)
else
Invariant.none

let query ctx (type a) (q: a Queries.t): a Queries.result =
let open Queries in
let st = ctx.local in
Expand All @@ -655,6 +664,9 @@ struct
let vf' x = vf (Obj.repr x) in
Priv.iter_sys_vars ctx.global vq vf'
| Queries.Invariant context -> query_invariant ctx context
| Queries.InvariantGlobal g ->
let g: V.t = Obj.obj g in
query_invariant_global ctx g
| _ -> Result.top q


Expand Down
42 changes: 42 additions & 0 deletions src/analyses/apron/relationPriv.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ module type S =
val thread_return: Q.ask -> (V.t -> G.t) -> (V.t -> G.t -> unit) -> ThreadIdDomain.Thread.t -> relation_components_t -> relation_components_t
val iter_sys_vars: (V.t -> G.t) -> VarQuery.t -> V.t VarQuery.f -> unit (** [Queries.IterSysVars] for apron. *)

val invariant_global: Q.ask -> (V.t -> G.t) -> V.t -> Invariant.t
(** Returns flow-insensitive invariant for global unknown. *)

val invariant_vars: Q.ask -> (V.t -> G.t) -> relation_components_t -> varinfo list
(** Returns global variables which are privatized. *)

Expand Down Expand Up @@ -137,6 +140,7 @@ struct
{rel = RD.top (); priv = startstate ()}

let iter_sys_vars getg vq vf = ()
let invariant_global ask getg g = Invariant.none
let invariant_vars ask getg st = []

let init () = ()
Expand Down Expand Up @@ -424,6 +428,7 @@ struct
{rel = getg (); priv = startstate ()}

let iter_sys_vars getg vq vf = () (* TODO: or report singleton global for any Global query? *)
let invariant_global ask getg g = Invariant.none
let invariant_vars ask getg st = protected_vars ask (* TODO: is this right? *)

let finalize () = ()
Expand Down Expand Up @@ -708,6 +713,41 @@ struct

let init () = ()
let finalize () = ()

let invariant_global (ask: Q.ask) (getg: V.t -> G.t): V.t -> Invariant.t = function
| `Left m' -> (* mutex *)
let atomic = LockDomain.MustLock.equal m' (LockDomain.MustLock.of_var LibraryFunctions.verifier_atomic_var) in
if atomic || ask.f (GhostVarAvailable (Locked m')) then (
(* filters like query_invariant *)
let one_var = GobConfig.get_bool "ana.relation.invariant.one-var" in
let exact = GobConfig.get_bool "witness.invariant.exact" in

let rel = keep_only_protected_globals ask m' (get_m_with_mutex_inits ask getg m') in (* Could be more precise if mutex_inits invariant is added by disjunction instead of joining abstract values. *)
let inv =
RD.invariant rel
|> List.enum
|> Enum.filter_map (fun (lincons1: Apron.Lincons1.t) ->
(* filter one-vars and exact *)
(* TODO: exact filtering doesn't really work with octagon because it returns two SUPEQ constraints instead *)
if (one_var || GobApron.Lincons1.num_vars lincons1 >= 2) && (exact || Apron.Lincons1.get_typ lincons1 <> EQ) then
RD.cil_exp_of_lincons1 lincons1
|> Option.filter (fun exp -> not (InvariantCil.exp_contains_tmp exp))
else
None
)
|> Enum.fold (fun acc x -> Invariant.(acc && of_exp x)) Invariant.none
in
if atomic then
inv
else (
let var = WitnessGhost.to_varinfo (Locked m') in
Invariant.(of_exp (Lval (GoblintCil.var var)) || inv) [@coverage off] (* bisect_ppx cannot handle redefined (||) *)
)
)
else
Invariant.none
| g -> (* global *)
Invariant.none (* Could output unprotected one-variable (so non-relational) invariants, but probably not very useful. [BasePriv] does those anyway. *)
end

(** May written variables. *)
Expand Down Expand Up @@ -1275,6 +1315,8 @@ struct
| _ -> ()

let finalize () = ()

let invariant_global ask getg g = Invariant.none
end

module TracingPriv = functor (Priv: S) -> functor (RD: RelationDomain.RD) ->
Expand Down
58 changes: 45 additions & 13 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,9 @@ struct
not is_alloc || (is_alloc && not (ctx.ask (Queries.IsHeapVar v)))

let query_invariant ctx context =
let keep_local = GobConfig.get_bool "ana.base.invariant.local" in
let keep_global = GobConfig.get_bool "ana.base.invariant.global" in
jerhard marked this conversation as resolved.
Show resolved Hide resolved

let cpa = ctx.local.BaseDomain.cpa in
let ask = Analyses.ask_of_ctx ctx in

Expand All @@ -1193,6 +1196,13 @@ struct
in
let module I = ValueDomain.ValueInvariant (Arg) in

let var_filter v =
if is_global ask v then
keep_global
else
keep_local
in

let var_invariant ?offset v =
if not (InvariantCil.var_is_heap v) then
I.key_invariant v ?offset (Arg.find v)
Expand All @@ -1203,14 +1213,23 @@ struct
if Lval.Set.is_top context.Invariant.lvals then (
if !earlyglobs || ThreadFlag.has_ever_been_multi ask then (
let cpa_invariant =
CPA.fold (fun k v a ->
if not (is_global ask k) then
Invariant.(a && var_invariant k)
else
a
) cpa Invariant.none
if keep_local then (
CPA.fold (fun k v a ->
if not (is_global ask k) then
Invariant.(a && var_invariant k)
else
a
) cpa Invariant.none
)
else
Invariant.none
in
let priv_vars =
if keep_global then
Priv.invariant_vars ask (priv_getg ctx.global) ctx.local
else
[]
in
let priv_vars = Priv.invariant_vars ask (priv_getg ctx.global) ctx.local in
let priv_invariant =
List.fold_left (fun acc v ->
Invariant.(var_invariant v && acc)
Expand All @@ -1220,15 +1239,18 @@ struct
)
else (
CPA.fold (fun k v a ->
Invariant.(a && var_invariant k)
if var_filter k then
Invariant.(a && var_invariant k)
else
a
) cpa Invariant.none
)
)
else (
Lval.Set.fold (fun k a ->
let i =
match k with
| (Var v, offset) when not (InvariantCil.var_is_heap v) ->
| (Var v, offset) when var_filter v && not (InvariantCil.var_is_heap v) ->
(try I.key_invariant_lval v ~offset ~lval:k (Arg.find v) with Not_found -> Invariant.none)
| _ -> Invariant.none
in
Expand All @@ -1243,13 +1265,23 @@ struct
Invariant.none

let query_invariant_global ctx g =
if GobConfig.get_bool "ana.base.invariant.enabled" && get_bool "exp.earlyglobs" then (
if GobConfig.get_bool "ana.base.invariant.enabled" && GobConfig.get_bool "ana.base.invariant.global" then (
(* Currently these global invariants are only sound with earlyglobs enabled for both single- and multi-threaded programs.
Otherwise, the values of globals in single-threaded mode are not accounted for. *)
(* TODO: account for single-threaded values without earlyglobs. *)
Otherwise, the values of globals in single-threaded mode are not accounted for.
They are also made sound without earlyglobs using the multithreaded mode ghost variable. *)
match g with
| `Left g' -> (* priv *)
Priv.invariant_global (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) g'
let inv = Priv.invariant_global (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) g' in
if get_bool "exp.earlyglobs" then
inv
else (
if ctx.ask (GhostVarAvailable Multithreaded) then (
let var = WitnessGhost.to_varinfo Multithreaded in
Invariant.(of_exp (UnOp (LNot, Lval (GoblintCil.var var), GoblintCil.intType)) || inv) [@coverage off] (* bisect_ppx cannot handle redefined (||) *)
)
else
Invariant.none
)
| `Right _ -> (* thread return *)
Invariant.none
)
Expand Down
Loading
Loading