Skip to content

Commit 848713d

Browse files
authored
Merge pull request #1859 from goblint/yaml-witness-2.1-version
Automatically determine generated YAML witness version
2 parents 7cfcc62 + ffe80aa commit 848713d

18 files changed

+127
-42
lines changed

src/config/options.schema.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,9 +2791,10 @@
27912791
"type": "string",
27922792
"enum": [
27932793
"2.0",
2794-
"2.1"
2794+
"2.1",
2795+
"2.1-goblint"
27952796
],
2796-
"default": "2.0"
2797+
"default": "2.1"
27972798
},
27982799
"entry-types": {
27992800
"title": "witness.yaml.entry-types",

src/goblint_lib.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ module WitnessUtil = WitnessUtil
360360

361361
module YamlWitness = YamlWitness
362362
module YamlWitnessType = YamlWitnessType
363+
module YamlWitnessVersion = YamlWitnessVersion
363364
module WitnessGhost = WitnessGhost
364365

365366
(** {2 SARIF} *)

src/witness/yamlWitness.ml

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,25 @@ struct
2121
command_line = Some GobSys.command_line;
2222
}
2323

24-
let metadata ?task (): Metadata.t =
24+
let metadata ~format_version ?task (): Metadata.t =
2525
let uuid = Uuidm.v4_gen uuid_random_state () in
26+
let conf_format_version = YamlWitnessVersion.of_option () in
27+
if YamlWitnessVersion.compare format_version conf_format_version > 0 then
28+
M.warn_noloc ~category:Witness "witness entry version (%a) exceeds configured witness.yaml.format-version (%a)" YamlWitnessVersion.pretty format_version YamlWitnessVersion.pretty conf_format_version;
2629
let creation_time = TimeUtil.iso8601_now () in
2730
{
28-
format_version = GobConfig.get_string "witness.yaml.format-version";
31+
format_version = YamlWitnessVersion.show format_version;
2932
uuid = Uuidm.to_string uuid;
3033
creation_time;
3134
producer;
3235
task
3336
}
3437

38+
let with_metadata ~task entry_type: Entry.t = {
39+
entry_type;
40+
metadata = metadata ~format_version:(EntryType.min_version entry_type) ~task ();
41+
}
42+
3543
let task ~input_files ~data_model ~(specification): Task.t =
3644
{
3745
input_files;
@@ -44,14 +52,9 @@ struct
4452
}
4553

4654
let location ~location:(loc: Cil.location) ~(location_function): Location.t =
47-
let file_hash =
48-
match GobConfig.get_string "witness.yaml.format-version" with
49-
| "2.0" -> None (* TODO: 2.1? *)
50-
| _ -> assert false
51-
in
5255
{
5356
file_name = loc.file;
54-
file_hash;
57+
file_hash = None;
5558
line = loc.line;
5659
column = Some loc.column;
5760
function_ = Some location_function;
@@ -86,12 +89,10 @@ struct
8689
};
8790
}
8891

89-
let invariant_set ~task ~(invariants): Entry.t = {
90-
entry_type = InvariantSet {
91-
content = invariants;
92-
};
93-
metadata = metadata ~task ();
94-
}
92+
let invariant_set ~task ~(invariants): Entry.t =
93+
with_metadata ~task @@ InvariantSet {
94+
content = invariants;
95+
}
9596

9697
let ghost_variable' ~variable ~type_ ~(initial): GhostInstrumentation.Variable.t = {
9798
name = variable;
@@ -114,13 +115,11 @@ struct
114115
updates;
115116
}
116117

117-
let ghost_instrumentation ~task ~variables ~(location_updates): Entry.t = {
118-
entry_type = GhostInstrumentation {
119-
ghost_variables = variables;
120-
ghost_updates = location_updates;
121-
};
122-
metadata = metadata ~task ();
123-
}
118+
let ghost_instrumentation ~task ~variables ~(location_updates): Entry.t =
119+
with_metadata ~task @@ GhostInstrumentation {
120+
ghost_variables = variables;
121+
ghost_updates = location_updates;
122+
}
124123
end
125124

126125
let yaml_entries_to_file yaml_entries file =

src/witness/yamlWitnessType.ml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ struct
165165

166166
let invariant_type = "loop_invariant"
167167

168+
let min_version = function
169+
| {labels = Some _; _} -> YamlWitnessVersion.V2_1
170+
| _ -> YamlWitnessVersion.V2_0
171+
168172
let to_yaml' {location; value; format; labels} =
169173
[
170174
("location", Location.to_yaml location);
@@ -197,13 +201,15 @@ struct
197201
include LoopInvariant
198202

199203
let invariant_type = "loop_transition_invariant"
204+
let min_version _ = YamlWitnessVersion.V2_1
200205
end
201206

202207
module LocationTransitionInvariant =
203208
struct
204209
include LoopTransitionInvariant
205210

206211
let invariant_type = "location_transition_invariant"
212+
let min_version _ = YamlWitnessVersion.V2_1
207213
end
208214

209215
module FlowInsensitiveInvariant =
@@ -215,6 +221,7 @@ struct
215221
[@@deriving eq, ord, hash]
216222

217223
let invariant_type = "flow_insensitive_invariant"
224+
let min_version _ = YamlWitnessVersion.V2_1_Goblint
218225

219226
let to_yaml' {value; format} =
220227
[
@@ -247,6 +254,13 @@ struct
247254
| LocationTransitionInvariant _ -> LocationTransitionInvariant.invariant_type
248255
| FlowInsensitiveInvariant _ -> FlowInsensitiveInvariant.invariant_type
249256

257+
let min_version = function
258+
| LocationInvariant x -> LocationInvariant.min_version x
259+
| LoopInvariant x -> LoopInvariant.min_version x
260+
| LoopTransitionInvariant x -> LoopTransitionInvariant.min_version x
261+
| LocationTransitionInvariant x -> LocationTransitionInvariant.min_version x
262+
| FlowInsensitiveInvariant x -> FlowInsensitiveInvariant.min_version x
263+
250264
let to_yaml' = function
251265
| LocationInvariant x -> LocationInvariant.to_yaml' x
252266
| LoopInvariant x -> LoopInvariant.to_yaml' x
@@ -285,6 +299,8 @@ struct
285299

286300
let invariant_kind = "invariant"
287301

302+
let min_version {invariant_type} = InvariantType.min_version invariant_type
303+
288304
let to_yaml {invariant_type} =
289305
`O [
290306
("invariant", `O ([
@@ -311,6 +327,7 @@ struct
311327
[@@deriving eq, ord, hash]
312328

313329
let contract_type = "function_contract"
330+
let min_version _ = YamlWitnessVersion.V2_1
314331

315332
let to_yaml' {location; requires; ensures; format; labels} =
316333
[
@@ -344,6 +361,9 @@ struct
344361
let contract_type = function
345362
| FunctionContract _ -> FunctionContract.contract_type
346363

364+
let min_version = function
365+
| FunctionContract x -> FunctionContract.min_version x
366+
347367
let to_yaml' = function
348368
| FunctionContract x -> FunctionContract.to_yaml' x
349369

@@ -366,6 +386,8 @@ struct
366386

367387
let invariant_kind = "contract"
368388

389+
let min_version {contract_type} = ContractType.min_version contract_type
390+
369391
let to_yaml {contract_type} =
370392
`O [
371393
("contract", `O ([
@@ -391,6 +413,10 @@ struct
391413
| Invariant _ -> Invariant.invariant_kind
392414
| Contract _ -> Contract.invariant_kind
393415

416+
let min_version = function
417+
| Invariant x -> Invariant.min_version x
418+
| Contract x -> Contract.min_version x
419+
394420
let to_yaml = function
395421
| Invariant x -> Invariant.to_yaml x
396422
| Contract x -> Contract.to_yaml x
@@ -419,6 +445,11 @@ struct
419445

420446
let entry_type = "invariant_set"
421447

448+
let min_version {content} =
449+
List.to_seq content
450+
|> Seq.map InvariantKind.min_version
451+
|> Seq.fold_left YamlWitnessVersion.max YamlWitnessVersion.V2_0
452+
422453
let to_yaml' {content} =
423454
[("content", `A (List.map InvariantKind.to_yaml content))]
424455

@@ -636,6 +667,7 @@ struct
636667
[@@deriving eq, ord, hash]
637668

638669
let entry_type = "violation_sequence"
670+
let min_version _ = YamlWitnessVersion.V2_0
639671

640672
let to_yaml' {content} =
641673
[("content", `A (List.map Segment.to_yaml content))]
@@ -749,6 +781,7 @@ struct
749781
[@@deriving eq, ord, hash]
750782

751783
let entry_type = "ghost_instrumentation"
784+
let min_version _ = YamlWitnessVersion.V2_1
752785

753786
let to_yaml' {ghost_variables; ghost_updates} =
754787
[("content",
@@ -780,6 +813,11 @@ struct
780813
| ViolationSequence _ -> ViolationSequence.entry_type
781814
| GhostInstrumentation _ -> GhostInstrumentation.entry_type
782815

816+
let min_version = function
817+
| InvariantSet x -> InvariantSet.min_version x
818+
| ViolationSequence x -> ViolationSequence.min_version x
819+
| GhostInstrumentation x -> GhostInstrumentation.min_version x
820+
783821
let to_yaml' = function
784822
| InvariantSet x -> InvariantSet.to_yaml' x
785823
| ViolationSequence x -> ViolationSequence.to_yaml' x

src/witness/yamlWitnessVersion.ml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
(** YAML witness format version. *)
2+
3+
type t =
4+
| V2_0
5+
| V2_1
6+
| V2_1_Goblint
7+
[@@deriving ord, enum]
8+
9+
let show = function
10+
| V2_0 -> "2.0"
11+
| V2_1 -> "2.1"
12+
| V2_1_Goblint -> "2.1-goblint"
13+
14+
include Printable.SimpleShow (
15+
struct
16+
type nonrec t = t
17+
let show = show
18+
end
19+
)
20+
21+
let of_string = function
22+
| "2.0" -> V2_0
23+
| "2.1" -> V2_1
24+
| "2.1-goblint" -> V2_1_Goblint
25+
| _ -> invalid_arg "YamlWitnessVersion.of_string"
26+
27+
let of_option () =
28+
of_string (GobConfig.get_string "witness.yaml.format-version")
29+
30+
let min x y =
31+
Option.get (of_enum (Int.min (to_enum x) (to_enum y)))
32+
33+
let max x y =
34+
Option.get (of_enum (Int.max (to_enum x) (to_enum y)))

tests/regression/13-privatized/01-priv_nr.t

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
unsafe: 0
2121
total memory locations: 1
2222

23+
$ grep format_version witness.yml
24+
format_version: "2.0"
25+
2326
$ yamlWitnessStrip < witness.yml
2427
- entry_type: invariant_set
2528
content:

tests/regression/13-privatized/04-priv_multi.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 04-priv_multi.c
1+
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 04-priv_multi.c
22
[Success][Assert] Assertion "p == 5" will succeed (04-priv_multi.c:50:7-50:30)
33
[Success][Assert] Assertion "A == B" will succeed (04-priv_multi.c:71:5-71:28)
44
[Warning][Deadcode] Function 'dispose' has dead code:

tests/regression/13-privatized/25-struct_nr.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 25-struct_nr.c
1+
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 25-struct_nr.c
22
[Success][Assert] Assertion "glob1 == 5" will succeed (25-struct_nr.c:26:3-26:30)
33
[Success][Assert] Assertion "t == 5" will succeed (25-struct_nr.c:16:3-16:26)
44
[Success][Assert] Assertion "glob1 == -10" will succeed (25-struct_nr.c:18:3-18:32)

tests/regression/13-privatized/74-mutex.t

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 74-mutex.c
1+
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 74-mutex.c
22
[Success][Assert] Assertion "used == 0" will succeed (74-mutex.c:37:3-37:29)
33
[Warning][Deadcode] Function 'producer' has dead code:
44
on line 26 (74-mutex.c:26-26)
@@ -18,6 +18,10 @@
1818
unsafe: 0
1919
total memory locations: 1
2020

21+
$ grep format_version witness.yml
22+
format_version: "2.1"
23+
format_version: 2.1-goblint
24+
2125
$ yamlWitnessStrip < witness.yml | tee witness.flow_insensitive.yml
2226
- entry_type: ghost_instrumentation
2327
content:
@@ -113,6 +117,11 @@ Flow-insensitive invariants as location invariants.
113117
unsafe: 0
114118
total memory locations: 1
115119

120+
TODO: should invariant_set-s which use ghosts also be 2.1?
121+
$ grep format_version witness.yml
122+
format_version: "2.1"
123+
format_version: "2.0"
124+
116125
$ yamlWitnessStrip < witness.yml > witness.location.yml
117126

118127
$ diff witness.flow_insensitive.yml witness.location.yml
@@ -261,7 +270,7 @@ Same with ghost_instrumentation and invariant_set entries.
261270

262271
Same protected invariant with vojdani but no unprotected invariant.
263272

264-
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization vojdani --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 74-mutex.c
273+
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization vojdani --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 74-mutex.c
265274
[Success][Assert] Assertion "used == 0" will succeed (74-mutex.c:37:3-37:29)
266275
[Warning][Deadcode] Function 'producer' has dead code:
267276
on line 26 (74-mutex.c:26-26)
@@ -352,7 +361,7 @@ Same protected invariant with vojdani but no unprotected invariant.
352361

353362
Same as protection with mutex-meet.
354363

355-
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization mutex-meet --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 74-mutex.c
364+
$ goblint --enable ana.sv-comp.functions --set ana.base.privatization mutex-meet --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 74-mutex.c
356365
[Success][Assert] Assertion "used == 0" will succeed (74-mutex.c:37:3-37:29)
357366
[Warning][Deadcode] Function 'producer' has dead code:
358367
on line 26 (74-mutex.c:26-26)

tests/regression/13-privatized/92-idx_priv.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant 92-idx_priv.c
1+
$ goblint --set ana.base.privatization protection --enable witness.yaml.enabled --set ana.activated[+] mutexGhosts --set witness.yaml.entry-types[+] ghost_instrumentation --set witness.yaml.invariant-types[*] flow_insensitive_invariant --set witness.yaml.format-version 2.1-goblint 92-idx_priv.c
22
[Success][Assert] Assertion "data == 0" will succeed (92-idx_priv.c:22:3-22:29)
33
[Info][Deadcode] Logical lines of code (LLoC) summary:
44
live: 14

0 commit comments

Comments
 (0)