Skip to content

Commit fa8113e

Browse files
committed
Merge branch 'master' into apron_track_address
2 parents e4d5d95 + 713f2a1 commit fa8113e

39 files changed

+1310
-499
lines changed

conf/traces-rel.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,18 @@
2626
]
2727
},
2828
"base" : {
29-
"privatization": "mutex-meet"
29+
"privatization": "mutex-meet",
30+
"invariant": {
31+
"enabled": false
32+
}
33+
},
34+
"apron": {
35+
"invariant": {
36+
"one-var": false,
37+
"local": false,
38+
"global": true,
39+
"diff-box": true
40+
}
3041
}
3142
},
3243
"sem": {
@@ -38,6 +49,9 @@
3849
},
3950
"builtin_unreachable": {
4051
"dead_code": true
52+
},
53+
"int": {
54+
"signed_overflow": "assume_none"
4155
}
4256
},
4357
"exp": {
@@ -52,5 +66,12 @@
5266
"print_tids" : true,
5367
"print_wpoints" : true,
5468
"print_protection": true
69+
},
70+
"witness": {
71+
"invariant": {
72+
"other": false,
73+
"loop-head": false,
74+
"after-lock": true
75+
}
5576
}
5677
}

make.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ rule() {
109109
cp g2html/g2html.jar .
110110
;; setup_gobview )
111111
[[ -f gobview/gobview.opam ]] || git submodule update --init gobview
112-
opam install --deps-only --locked gobview/gobview.opam
112+
opam install --deps-only --locked gobview/
113113
# ;; watch)
114114
# fswatch --event Updated -e $TARGET.ml src/ | xargs -n1 -I{} make
115115
;; install)

scripts/update_suite.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,12 @@ def collect_warnings
156156
when /Assertion .* will fail/ then "fail"
157157
when /Assertion .* will succeed/ then "success"
158158
when /Assertion .* is unknown/ then "unknown"
159+
when /invariant confirmed/ then "success"
160+
when /invariant unconfirmed/ then "unknown"
161+
when /invariant refuted/ then "fail"
159162
when /^\[Warning\]/ then "warn"
160163
when /^\[Error\]/ then "warn"
164+
when /^\[Success\]/ then "success"
161165
when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN)
162166
when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN)
163167
when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN)
@@ -192,7 +196,7 @@ def compare_warnings
192196
check.call warnings[idx] == type
193197
when "nowarn"
194198
check.call warnings[idx].nil?
195-
when "assert"
199+
when "assert", "success"
196200
check.call warnings[idx] == "success"
197201
when "norace"
198202
check.call warnings[idx] != "race"
@@ -285,6 +289,12 @@ def parse_tests (lines)
285289
tests[i] = if obj =~ /NODEADLOCK/ then "nodeadlock" else "deadlock" end
286290
elsif obj =~ /WARN/ then
287291
tests[i] = if obj =~ /NOWARN/ then "nowarn" else "warn" end
292+
elsif obj =~ /SUCCESS/ then
293+
tests[i] = "success"
294+
elsif obj =~ /FAIL/ then
295+
tests[i] = "fail"
296+
elsif obj =~ /UNKNOWN/ then
297+
tests[i] = "unknown"
288298
elsif obj =~ /assert.*\(/ then
289299
if obj =~ /FAIL/ then
290300
tests[i] = "fail"

src/analyses/apron/apronAnalysis.apron.ml

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ open ApronDomain
66

77
module M = Messages
88

9-
module SpecFunctor (AD: ApronDomain.S2) (Priv: ApronPriv.S) : Analyses.MCPSpec =
9+
module SpecFunctor (AD: ApronDomain.S3) (Priv: ApronPriv.S) : Analyses.MCPSpec =
1010
struct
1111
include Analyses.DefaultSpec
1212

1313
let name () = "apron"
1414

15+
module AD =
16+
struct
17+
include AD
18+
include ApronDomain.Tracked
19+
end
20+
1521
module Priv = Priv(AD)
1622
module D = ApronComponents (AD) (Priv.D)
1723
module G = Priv.G
@@ -334,7 +340,7 @@ struct
334340
| _ -> false (* remove everything else (globals, global privs, reachable things from the caller) *)
335341
)
336342
in
337-
let unify_apr = ApronDomain.A.unify Man.mgr new_apr new_fun_apr in (* TODO: unify_with *)
343+
let unify_apr = AD.unify new_apr new_fun_apr in (* TODO: unify_with *)
338344
if M.tracing then M.tracel "combine" "apron unifying %a %a = %a\n" AD.pretty new_apr AD.pretty new_fun_apr AD.pretty unify_apr;
339345
let unify_st = {fun_st with apr = unify_apr} in
340346
if AD.type_tracked (Cilfacade.fundec_return_type f) then (
@@ -443,6 +449,34 @@ struct
443449
| None -> st'
444450

445451

452+
let query_invariant ctx context =
453+
let keep_local = GobConfig.get_bool "ana.apron.invariant.local" in
454+
let keep_global = GobConfig.get_bool "ana.apron.invariant.global" in
455+
456+
let apr = ctx.local.apr in
457+
(* filter variables *)
458+
let var_filter v = match V.find_metadata v with
459+
| Some (Global _) -> keep_global
460+
| Some Local -> keep_local
461+
| _ -> false
462+
in
463+
let apr = AD.keep_filter apr var_filter in
464+
465+
let one_var = GobConfig.get_bool "ana.apron.invariant.one-var" in
466+
let scope = Node.find_fundec ctx.node in
467+
468+
AD.invariant ~scope apr
469+
|> List.enum
470+
|> Enum.filter_map (fun (lincons1: Lincons1.t) ->
471+
(* filter one-vars *)
472+
if one_var || Apron.Linexpr0.get_size lincons1.lincons0.linexpr0 >= 2 then
473+
CilOfApron.cil_exp_of_lincons1 scope lincons1
474+
|> Option.filter (fun exp -> not (InvariantCil.exp_contains_tmp exp) && InvariantCil.exp_is_in_scope scope exp)
475+
else
476+
None
477+
)
478+
|> Enum.fold (fun acc x -> Invariant.(acc && of_exp x)) Invariant.none
479+
446480
let query ctx (type a) (q: a Queries.t): a Queries.result =
447481
let open Queries in
448482
let st = ctx.local in
@@ -472,6 +506,8 @@ struct
472506
let exp = (BinOp (Cil.Lt, exp1, exp2, TInt (IInt, []))) in
473507
let is_lt = eval_int exp in
474508
Option.default true (ID.to_bool is_lt)
509+
| Queries.Invariant context ->
510+
query_invariant ctx context
475511
| _ -> Result.top q
476512

477513

@@ -523,8 +559,19 @@ struct
523559
let sync ctx reason =
524560
(* After the solver is finished, store the results (for later comparison) *)
525561
if !GU.postsolving then begin
562+
let keep_local = GobConfig.get_bool "ana.apron.invariant.local" in
563+
let keep_global = GobConfig.get_bool "ana.apron.invariant.global" in
564+
565+
(* filter variables *)
566+
let var_filter v = match V.find_metadata v with
567+
| Some (Global _) -> keep_global
568+
| Some Local -> keep_local
569+
| _ -> false
570+
in
571+
let st = keep_filter ctx.local.apr var_filter in
572+
526573
let old_value = RH.find_default results ctx.node (AD.bot ()) in
527-
let new_value = AD.join old_value ctx.local.apr in
574+
let new_value = AD.join old_value st in
528575
RH.replace results ctx.node new_value;
529576
end;
530577
Priv.sync (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg ctx.local (reason :> [`Normal | `Join | `Return | `Init | `Thread])
@@ -535,21 +582,14 @@ struct
535582
module OctApron = ApronPrecCompareUtil.OctagonD
536583
let store_data file =
537584
let convert (m: AD.t RH.t): OctApron.t RH.t =
538-
let convert_single (a: AD.t): OctApron.t =
539-
if Oct.manager_is_oct AD.Man.mgr then
540-
Oct.Abstract1.to_oct a
541-
else
542-
let generator = AD.to_lincons_array a in
543-
OctApron.of_lincons_array generator
544-
in
545-
RH.map (fun _ -> convert_single) m
585+
RH.map (fun _ -> AD.to_oct) m
546586
in
547587
let post_process m =
548588
let m = Stats.time "convert" convert m in
549589
RH.map (fun _ v -> OctApron.marshal v) m
550590
in
551591
let results = post_process results in
552-
let name = name () ^ "(domain: " ^ (AD.Man.name ()) ^ ", privatization: " ^ (Priv.name ()) ^ (if GobConfig.get_bool "ana.apron.threshold_widening" then ", th" else "" ) ^ ")" in
592+
let name = name () ^ "(domain: " ^ (AD.name ()) ^ ", privatization: " ^ (Priv.name ()) ^ (if GobConfig.get_bool "ana.apron.threshold_widening" then ", th" else "" ) ^ ")" in
553593
let results: ApronPrecCompareUtil.dump = {marshalled = results; name } in
554594
Serialize.marshal results file
555595

@@ -566,7 +606,9 @@ end
566606
let spec_module: (module MCPSpec) Lazy.t =
567607
lazy (
568608
let module Man = (val ApronDomain.get_manager ()) in
569-
let module AD = ApronDomain.D2 (Man) in
609+
let module AD = ApronDomain.D3 (Man) in
610+
let diff_box = GobConfig.get_bool "ana.apron.invariant.diff-box" in
611+
let module AD = (val if diff_box then (module ApronDomain.BoxProd (AD): ApronDomain.S3) else (module AD)) in
570612
let module Priv = (val ApronPriv.get_priv ()) in
571613
let module Spec = SpecFunctor (AD) (Priv) in
572614
(module Spec)

src/analyses/apron/apronPriv.apron.ml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ open CommonPriv
1212

1313

1414
module type S =
15-
functor (AD: ApronDomain.S2) ->
15+
functor (AD: ApronDomain.S3) ->
1616
sig
1717
module D: Lattice.S
1818
module G: Lattice.S
@@ -47,7 +47,7 @@ module type S =
4747

4848
(** Top privatization, which doesn't track globals at all.
4949
This is unlike base's "none" privatization. which does track globals, but doesn't privatize them. *)
50-
module Top: S = functor (AD: ApronDomain.S2) ->
50+
module Top: S = functor (AD: ApronDomain.S3) ->
5151
struct
5252
module D = Lattice.Unit
5353
module G = Lattice.Unit
@@ -139,7 +139,7 @@ sig
139139
end
140140

141141
(** Protection-Based Reading. Is unsound w.r.t. to locals escaping and becoming public. *)
142-
module ProtectionBasedPriv (Param: ProtectionBasedPrivParam): S = functor (AD: ApronDomain.S2) ->
142+
module ProtectionBasedPriv (Param: ProtectionBasedPrivParam): S = functor (AD: ApronDomain.S3) ->
143143
struct
144144
include ConfCheck.RequireMutexActivatedInit
145145
open Protection
@@ -406,7 +406,7 @@ struct
406406
let finalize () = ()
407407
end
408408

409-
module CommonPerMutex = functor(AD: ApronDomain.S2) ->
409+
module CommonPerMutex = functor(AD: ApronDomain.S3) ->
410410
struct
411411
include Protection
412412
module V = ApronDomain.V
@@ -429,7 +429,7 @@ struct
429429
end
430430

431431
(** Per-mutex meet. *)
432-
module PerMutexMeetPriv : S = functor (AD: ApronDomain.S2) ->
432+
module PerMutexMeetPriv : S = functor (AD: ApronDomain.S3) ->
433433
struct
434434
open CommonPerMutex(AD)
435435
include MutexGlobals
@@ -572,7 +572,7 @@ struct
572572

573573
let escape node ask getg sideg (st:apron_components_t) escaped : apron_components_t =
574574
let esc_vars = EscapeDomain.EscapedVars.elements escaped in
575-
let esc_vars = List.filter (fun v -> not v.vglob && AD.varinfo_tracked v && AD.mem_var st.apr (AV.local v)) esc_vars in
575+
let esc_vars = List.filter (fun v -> not v.vglob && ApronDomain.Tracked.varinfo_tracked v && AD.mem_var st.apr (AV.local v)) esc_vars in
576576
let escape_one (x:varinfo) st = write_global ask getg sideg st x x in
577577
List.fold_left (fun st v -> escape_one v st) st esc_vars
578578

@@ -590,7 +590,7 @@ struct
590590
let name () = "W"
591591
end
592592

593-
module type ClusterArg = functor (AD: ApronDomain.S2) ->
593+
module type ClusterArg = functor (AD: ApronDomain.S3) ->
594594
sig
595595
module LAD: Lattice.S
596596

@@ -604,7 +604,7 @@ sig
604604
end
605605

606606
(** No clustering. *)
607-
module NoCluster:ClusterArg = functor (AD: ApronDomain.S2) ->
607+
module NoCluster:ClusterArg = functor (AD: ApronDomain.S3) ->
608608
struct
609609
module AD = AD
610610
open CommonPerMutex(AD)
@@ -687,7 +687,7 @@ end
687687

688688

689689
(** Clusters when clustering is downward-closed. *)
690-
module DownwardClosedCluster (ClusteringArg: ClusteringArg) = functor (AD: ApronDomain.S2) ->
690+
module DownwardClosedCluster (ClusteringArg: ClusteringArg) = functor (AD: ApronDomain.S3) ->
691691
struct
692692
module AD = AD
693693
open CommonPerMutex(AD)
@@ -752,7 +752,7 @@ struct
752752
end
753753

754754
(** Clusters when clustering is arbitrary (not necessarily downward-closed). *)
755-
module ArbitraryCluster (ClusteringArg: ClusteringArg): ClusterArg = functor (AD: ApronDomain.S2) ->
755+
module ArbitraryCluster (ClusteringArg: ClusteringArg): ClusterArg = functor (AD: ApronDomain.S3) ->
756756
struct
757757
module AD = AD
758758
module DCCluster = (DownwardClosedCluster(ClusteringArg))(AD)
@@ -828,7 +828,7 @@ struct
828828
end
829829

830830
(** Per-mutex meet with TIDs. *)
831-
module PerMutexMeetPrivTID (Cluster: ClusterArg): S = functor (AD: ApronDomain.S2) ->
831+
module PerMutexMeetPrivTID (Cluster: ClusterArg): S = functor (AD: ApronDomain.S3) ->
832832
struct
833833
open CommonPerMutex(AD)
834834
include MutexGlobals
@@ -1094,7 +1094,7 @@ struct
10941094

10951095
let escape node ask getg sideg (st: apron_components_t) escaped: apron_components_t =
10961096
let esc_vars = EscapeDomain.EscapedVars.elements escaped in
1097-
let esc_vars = List.filter (fun v -> not v.vglob && AD.varinfo_tracked v && AD.mem_var st.apr (AV.local v)) esc_vars in
1097+
let esc_vars = List.filter (fun v -> not v.vglob && ApronDomain.Tracked.varinfo_tracked v && AD.mem_var st.apr (AV.local v)) esc_vars in
10981098
let escape_one (x:varinfo) st = write_global ask getg sideg st x x in
10991099
List.fold_left (fun st v -> escape_one v st) st esc_vars
11001100

@@ -1125,7 +1125,7 @@ struct
11251125
let finalize () = finalize ()
11261126
end
11271127

1128-
module TracingPriv = functor (Priv: S) -> functor (AD: ApronDomain.S2) ->
1128+
module TracingPriv = functor (Priv: S) -> functor (AD: ApronDomain.S3) ->
11291129
struct
11301130
module Priv = Priv (AD)
11311131
include Priv

0 commit comments

Comments
 (0)