Skip to content

Commit d287916

Browse files
authored
Merge pull request #1596 from goblint/yaml-witness-invariant-set-widen-token
Add YAML `invariant_set` indices to widening tokens
2 parents d7074f1 + a281744 commit d287916

12 files changed

+131
-37
lines changed

src/analyses/apron/relationAnalysis.apron.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ struct
690690
Priv.lock ask ctx.global st m
691691
) st addr
692692
| Events.Unlock addr when ThreadFlag.has_ever_been_multi ask -> (* TODO: is this condition sound? *)
693-
WideningTokens.with_local_side_tokens (fun () ->
693+
WideningTokenLifter.with_local_side_tokens (fun () ->
694694
CommonPriv.lift_unlock ask (fun st m ->
695695
Priv.unlock ask ctx.global ctx.sideg st m
696696
) st addr
@@ -701,7 +701,7 @@ struct
701701
Priv.escape ctx.node (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg st escaped
702702
| Assert exp ->
703703
assert_fn ctx exp true
704-
| Events.Unassume {exp = e; uuids} ->
704+
| Events.Unassume {exp = e; tokens} ->
705705
let e_orig = e in
706706
let ask = Analyses.ask_of_ctx ctx in
707707
let e = replace_deref_exps ctx.ask e in
@@ -737,7 +737,7 @@ struct
737737

738738
(* TODO: parallel write_global? *)
739739
let st =
740-
WideningTokens.with_side_tokens (WideningTokens.TS.of_list uuids) (fun () ->
740+
WideningTokenLifter.with_side_tokens (WideningTokenLifter.TS.of_list tokens) (fun () ->
741741
VH.fold (fun v v_in st ->
742742
(* TODO: is this sideg fine? *)
743743
write_global ask ctx.global ctx.sideg st v v_in
@@ -771,7 +771,7 @@ struct
771771
let new_value = RD.join old_value st in
772772
PCU.RH.replace results ctx.node new_value;
773773
end;
774-
WideningTokens.with_local_side_tokens (fun () ->
774+
WideningTokenLifter.with_local_side_tokens (fun () ->
775775
Priv.sync (Analyses.ask_of_ctx ctx) ctx.global ctx.sideg ctx.local (reason :> [`Normal | `Join | `JoinCall of CilType.Fundec.t | `Return | `Init | `Thread])
776776
)
777777

src/analyses/base.ml

+5-5
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ struct
445445
in
446446
if M.tracing then M.tracel "sync" "sync multi=%B earlyglobs=%B" multi !earlyglobs;
447447
if !earlyglobs || multi then
448-
WideningTokens.with_local_side_tokens (fun () ->
448+
WideningTokenLifter.with_local_side_tokens (fun () ->
449449
Priv.sync (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) (priv_sideg ctx.sideg) ctx.local reason
450450
)
451451
else
@@ -3060,7 +3060,7 @@ struct
30603060
(* Perform actual [set]-s with final unassumed values.
30613061
This invokes [Priv.write_global], which was suppressed above. *)
30623062
let e_d' =
3063-
WideningTokens.with_side_tokens (WideningTokens.TS.of_list uuids) (fun () ->
3063+
WideningTokenLifter.with_side_tokens (WideningTokenLifter.TS.of_list uuids) (fun () ->
30643064
CPA.fold (fun x v acc ->
30653065
let addr: AD.t = AD.of_mval (x, `NoOffset) in
30663066
set ~ctx ~invariant:false acc addr x.vtype v
@@ -3079,7 +3079,7 @@ struct
30793079
Priv.lock ask (priv_getg ctx.global) st m
30803080
) st addr
30813081
| Events.Unlock addr when ThreadFlag.has_ever_been_multi ask -> (* TODO: is this condition sound? *)
3082-
WideningTokens.with_local_side_tokens (fun () ->
3082+
WideningTokenLifter.with_local_side_tokens (fun () ->
30833083
CommonPriv.lift_unlock ask (fun st m ->
30843084
Priv.unlock ask (priv_getg ctx.global) (priv_sideg ctx.sideg) st m
30853085
) st addr
@@ -3093,8 +3093,8 @@ struct
30933093
set ~ctx ctx.local (eval_lv ~ctx ctx.local lval) (Cilfacade.typeOfLval lval) (Thread (ValueDomain.Threads.singleton tid))
30943094
| Events.Assert exp ->
30953095
assert_fn ctx exp true
3096-
| Events.Unassume {exp; uuids} ->
3097-
Timing.wrap "base unassume" (unassume ctx exp) uuids
3096+
| Events.Unassume {exp; tokens} ->
3097+
Timing.wrap "base unassume" (unassume ctx exp) tokens
30983098
| Events.Longjmped {lval} ->
30993099
begin match lval with
31003100
| Some lval ->

src/analyses/mCP.ml

+6-6
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,20 @@ struct
156156
else
157157
iter (uncurry spawn_one) @@ group_assoc_eq Basetype.Variables.equal xs
158158

159-
let do_sideg ctx (xs:(V.t * (WideningTokens.TS.t * G.t)) list) =
159+
let do_sideg ctx (xs:(V.t * (WideningTokenLifter.TS.t * G.t)) list) =
160160
let side_one v dts =
161161
let side_one_ts ts d =
162162
(* Do side effects with the tokens that were active at the time.
163163
Transfer functions have exited the with_side_token wrappers by now. *)
164-
let old_side_tokens = !WideningTokens.side_tokens in
165-
WideningTokens.side_tokens := ts;
164+
let old_side_tokens = !WideningTokenLifter.side_tokens in
165+
WideningTokenLifter.side_tokens := ts;
166166
Fun.protect (fun () ->
167167
ctx.sideg v @@ fold_left G.join (G.bot ()) d
168168
) ~finally:(fun () ->
169-
WideningTokens.side_tokens := old_side_tokens
169+
WideningTokenLifter.side_tokens := old_side_tokens
170170
)
171171
in
172-
iter (uncurry side_one_ts) @@ group_assoc_eq WideningTokens.TS.equal dts
172+
iter (uncurry side_one_ts) @@ group_assoc_eq WideningTokenLifter.TS.equal dts
173173
in
174174
iter (uncurry side_one) @@ group_assoc_eq V.equal xs
175175

@@ -355,7 +355,7 @@ struct
355355
| None -> (fun ?(multiple=false) v d -> failwith ("Cannot \"spawn\" in " ^ tfname ^ " context."))
356356
in
357357
let sideg = match sides with
358-
| Some sides -> (fun v g -> sides := (v, (!WideningTokens.side_tokens, g)) :: !sides)
358+
| Some sides -> (fun v g -> sides := (v, (!WideningTokenLifter.side_tokens, g)) :: !sides)
359359
| None -> (fun v g -> failwith ("Cannot \"sideg\" in " ^ tfname ^ " context."))
360360
in
361361
let emit = match emits with

src/analyses/unassumeAnalysis.ml

+15-15
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct
2929

3030
type inv = {
3131
exp: Cil.exp;
32-
uuid: string;
32+
token: WideningToken.t;
3333
}
3434

3535
let invs: inv NH.t = NH.create 100
@@ -90,7 +90,7 @@ struct
9090
let uuid = entry.metadata.uuid in
9191
let target_type = YamlWitnessType.EntryType.entry_type entry.entry_type in
9292

93-
let unassume_nodes_invariant ~loc ~nodes inv =
93+
let unassume_nodes_invariant ~loc ~nodes ?i inv =
9494
let msgLoc: M.Location.t = CilLocation loc in
9595
match InvariantParser.parse_cabs inv with
9696
| Ok inv_cabs ->
@@ -101,7 +101,7 @@ struct
101101
match InvariantParser.parse_cil inv_parser ~check:false ~fundec ~loc inv_cabs with
102102
| Ok inv_exp ->
103103
M.debug ~category:Witness ~loc:msgLoc "located invariant to %a: %a" Node.pretty n Cil.d_exp inv_exp;
104-
NH.add invs n {exp = inv_exp; uuid}
104+
NH.add invs n {exp = inv_exp; token = (uuid, i)}
105105
| Error e ->
106106
M.error ~category:Witness ~loc:msgLoc "CIL couldn't parse invariant: %s" inv;
107107
M.info ~category:Witness ~loc:msgLoc "invariant has undefined variables or side effects: %s" inv
@@ -154,7 +154,7 @@ struct
154154
M.debug ~category:Witness ~loc:msgLoc "located invariant to %a: %a" Node.pretty n Cil.d_exp inv_exp;
155155
if not (NH.mem pre_invs n) then
156156
NH.replace pre_invs n (EH.create 10);
157-
EH.add (NH.find pre_invs n) pre_exp {exp = inv_exp; uuid}
157+
EH.add (NH.find pre_invs n) pre_exp {exp = inv_exp; token = (uuid, None)}
158158
| Error e ->
159159
M.error ~category:Witness ~loc:msgLoc "CIL couldn't parse invariant: %s" inv;
160160
M.info ~category:Witness ~loc:msgLoc "invariant has undefined variables or side effects: %s" inv
@@ -189,42 +189,42 @@ struct
189189

190190
let unassume_invariant_set (invariant_set: YamlWitnessType.InvariantSet.t) =
191191

192-
let unassume_location_invariant (location_invariant: YamlWitnessType.InvariantSet.LocationInvariant.t) =
192+
let unassume_location_invariant ~i (location_invariant: YamlWitnessType.InvariantSet.LocationInvariant.t) =
193193
let loc = YamlWitness.loc_of_location location_invariant.location in
194194
let inv = location_invariant.value in
195195
let msgLoc: M.Location.t = CilLocation loc in
196196

197197
match Locator.find_opt location_locator loc with
198198
| Some nodes ->
199-
unassume_nodes_invariant ~loc ~nodes inv
199+
unassume_nodes_invariant ~loc ~nodes ~i inv
200200
| None ->
201201
M.warn ~category:Witness ~loc:msgLoc "couldn't locate invariant: %s" inv
202202
in
203203

204-
let unassume_loop_invariant (loop_invariant: YamlWitnessType.InvariantSet.LoopInvariant.t) =
204+
let unassume_loop_invariant ~i (loop_invariant: YamlWitnessType.InvariantSet.LoopInvariant.t) =
205205
let loc = YamlWitness.loc_of_location loop_invariant.location in
206206
let inv = loop_invariant.value in
207207
let msgLoc: M.Location.t = CilLocation loc in
208208

209209
match Locator.find_opt loop_locator loc with
210210
| Some nodes ->
211-
unassume_nodes_invariant ~loc ~nodes inv
211+
unassume_nodes_invariant ~loc ~nodes ~i inv
212212
| None ->
213213
M.warn ~category:Witness ~loc:msgLoc "couldn't locate invariant: %s" inv
214214
in
215215

216-
let validate_invariant (invariant: YamlWitnessType.InvariantSet.Invariant.t) =
216+
let validate_invariant i (invariant: YamlWitnessType.InvariantSet.Invariant.t) =
217217
let target_type = YamlWitnessType.InvariantSet.InvariantType.invariant_type invariant.invariant_type in
218218
match YamlWitness.invariant_type_enabled target_type, invariant.invariant_type with
219219
| true, LocationInvariant x ->
220-
unassume_location_invariant x
220+
unassume_location_invariant ~i x
221221
| true, LoopInvariant x ->
222-
unassume_loop_invariant x
222+
unassume_loop_invariant ~i x
223223
| false, (LocationInvariant _ | LoopInvariant _) ->
224224
M.info_noloc ~category:Witness "disabled invariant of type %s" target_type
225225
in
226226

227-
List.iter validate_invariant invariant_set.content
227+
List.iteri validate_invariant invariant_set.content
228228
in
229229

230230
match YamlWitness.entry_type_enabled target_type, entry.entry_type with
@@ -262,9 +262,9 @@ struct
262262
M.info ~category:Witness "unassume invariant: %a" CilType.Exp.pretty e;
263263
if not !AnalysisState.postsolving then (
264264
if not (GobConfig.get_bool "ana.unassume.precheck" && Queries.ID.to_bool (ctx.ask (EvalInt e)) = Some false) then (
265-
let uuids = x.uuid :: List.map (fun {uuid; _} -> uuid) xs in
266-
ctx.emit (Unassume {exp = e; uuids});
267-
List.iter WideningTokens.add uuids
265+
let tokens = x.token :: List.map (fun {token; _} -> token) xs in
266+
ctx.emit (Unassume {exp = e; tokens});
267+
List.iter WideningTokenLifter.add tokens
268268
)
269269
);
270270
ctx.local

src/domains/events.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type t =
1414
| Assign of {lval: CilType.Lval.t; exp: CilType.Exp.t} (** Used to simulate old [ctx.assign]. *) (* TODO: unused *)
1515
| UpdateExpSplit of exp (** Used by expsplit analysis to evaluate [exp] on post-state. *)
1616
| Assert of exp
17-
| Unassume of {exp: CilType.Exp.t; uuids: string list}
17+
| Unassume of {exp: CilType.Exp.t; tokens: WideningToken.t list}
1818
| Longjmped of {lval: CilType.Lval.t option}
1919

2020
(** Should event be emitted after transfer function raises [Deadcode]? *)
@@ -45,5 +45,5 @@ let pretty () = function
4545
| Assign {lval; exp} -> dprintf "Assign {lval=%a, exp=%a}" CilType.Lval.pretty lval CilType.Exp.pretty exp
4646
| UpdateExpSplit exp -> dprintf "UpdateExpSplit %a" d_exp exp
4747
| Assert exp -> dprintf "Assert %a" d_exp exp
48-
| Unassume {exp; uuids} -> dprintf "Unassume {exp=%a; uuids=%a}" d_exp exp (docList Pretty.text) uuids
48+
| Unassume {exp; tokens} -> dprintf "Unassume {exp=%a; tokens=%a}" d_exp exp (d_list ", " WideningToken.pretty) tokens
4949
| Longjmped {lval} -> dprintf "Longjmped {lval=%a}" (docOpt (CilType.Lval.pretty ())) lval

src/framework/control.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let spec_module: (module Spec) Lazy.t = lazy (
3939
|> lift (get_bool "ana.opt.hashcons") (module HashconsLifter)
4040
(* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens.
4141
Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *)
42-
|> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter)
42+
|> lift (get_bool "ana.widen.tokens") (module WideningTokenLifter.Lifter)
4343
|> lift true (module LongjmpLifter.Lifter)
4444
|> lift termination_enabled (module RecursionTermLifter.Lifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*)
4545
)

src/goblint_lib.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ module SpecLifters = SpecLifters
180180
module LongjmpLifter = LongjmpLifter
181181
module RecursionTermLifter = RecursionTermLifter
182182
module ContextGasLifter = ContextGasLifter
183-
module WideningTokens = WideningTokens
183+
module WideningToken = WideningToken
184+
module WideningTokenLifter = WideningTokenLifter
184185

185186
module WitnessConstraints = WitnessConstraints
186187

src/lifters/wideningToken.ml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(** Widening token for {!WideningTokenLifter}. *)
2+
3+
module Uuid =
4+
struct
5+
include Basetype.RawStrings
6+
let name () = "uuid"
7+
end
8+
9+
module Index =
10+
struct
11+
include Printable.Option (IntDomain.Integers (IntOps.NIntOps)) (struct let name = "None" end)
12+
let name () = "index"
13+
end
14+
15+
(* Change to variant type if need other tokens than witness UUIDs. *)
16+
include Printable.Prod (Uuid) (Index)

src/lifters/wideningTokens.ml renamed to src/lifters/wideningTokenLifter.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
77
@see <http://www2.in.tum.de/bib/files/mihaila13widening.pdf> Mihaila, B., Sepp, A. & Simon, A. Widening as Abstract Domain. *)
88

9-
(** Widening token. *)
10-
module Token = Basetype.RawStrings (* Change to variant type if need other tokens than witness UUIDs. *)
9+
module Token = WideningToken
1110

1211
(** Widening token set. *)
1312
module TS = SetDomain.ToppedSet (Token) (struct let topname = "Top" end)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SKIP PARAM: --set ana.activated[+] apron --set ana.activated[+] unassume --set witness.yaml.unassume 64-apron-unassume-set-tokens.yml --set ana.apron.domain polyhedra --enable ana.widen.tokens
2+
#include <assert.h>
3+
// Uses polyhedra instead of octagon such that widening tokens are actually needed by test instead of narrowing.
4+
// Copied & extended from 56-witness/12-apron-unassume-branch.
5+
int main() {
6+
int i = 0;
7+
while (i < 100) {
8+
i++;
9+
}
10+
assert(i == 100);
11+
12+
int j = 0;
13+
while (j < 100) {
14+
j++;
15+
}
16+
assert(j == 100);
17+
return 0;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
- entry_type: invariant_set
2+
metadata:
3+
format_version: "0.1"
4+
uuid: 0a72f7b3-7826-4f68-bc7b-25425e95946e
5+
creation_time: 2022-07-26T09:11:03Z
6+
producer:
7+
name: Goblint
8+
version: heads/yaml-witness-unassume-0-g48503c690-dirty
9+
command_line: '''./goblint'' ''--enable'' ''dbg.debug'' ''--enable'' ''dbg.regression''
10+
''--html'' ''--set'' ''ana.activated[+]'' ''apron'' ''--enable'' ''witness.yaml.enabled''
11+
''64-apron-unassume-set-tokens.c'''
12+
task:
13+
input_files:
14+
- 64-apron-unassume-set-tokens.c
15+
input_file_hashes:
16+
64-apron-unassume-set-tokens.c: 71e40ed99b5217343d0831e293e7207e5bd30ce53f6ab73f0c1ef6ced1afcc60
17+
data_model: LP64
18+
language: C
19+
content:
20+
- invariant:
21+
type: location_invariant
22+
location:
23+
file_name: 64-apron-unassume-set-tokens.c
24+
file_hash: 71e40ed99b5217343d0831e293e7207e5bd30ce53f6ab73f0c1ef6ced1afcc60
25+
line: 8
26+
column: 3
27+
function: main
28+
value: 99LL - (long long )i >= 0LL
29+
format: c_expression
30+
- invariant:
31+
type: location_invariant
32+
location:
33+
file_name: 64-apron-unassume-set-tokens.c
34+
file_hash: 71e40ed99b5217343d0831e293e7207e5bd30ce53f6ab73f0c1ef6ced1afcc60
35+
line: 8
36+
column: 3
37+
function: main
38+
value: (long long )i >= 0LL
39+
format: c_expression
40+
- invariant:
41+
type: location_invariant
42+
location:
43+
file_name: 64-apron-unassume-set-tokens.c
44+
file_hash: 71e40ed99b5217343d0831e293e7207e5bd30ce53f6ab73f0c1ef6ced1afcc60
45+
line: 14
46+
column: 3
47+
function: main
48+
value: 99LL - (long long )j >= 0LL
49+
format: c_expression
50+
- invariant:
51+
type: location_invariant
52+
location:
53+
file_name: 64-apron-unassume-set-tokens.c
54+
file_hash: 71e40ed99b5217343d0831e293e7207e5bd30ce53f6ab73f0c1ef6ced1afcc60
55+
line: 14
56+
column: 3
57+
function: main
58+
value: (long long )j >= 0LL
59+
format: c_expression

tests/regression/56-witness/dune

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
(run %{update_suite} hh-ex3 -q)
2222
(run %{update_suite} bh-ex1-poly -q)
2323
(run %{update_suite} apron-unassume-precheck -q)
24-
(run %{update_suite} apron-tracked-global-annot -q)))))
24+
(run %{update_suite} apron-tracked-global-annot -q)
25+
(run %{update_suite} apron-unassume-set-tokens -q)))))
2526

2627
(cram
2728
(deps (glob_files *.c) (glob_files ??-*.yml)))

0 commit comments

Comments
 (0)