Skip to content

Commit 604ea39

Browse files
Reject witness on duplicate ghost variable declarations
1 parent ad88403 commit 604ea39

1 file changed

Lines changed: 65 additions & 1 deletion

File tree

src/witness/yamlWitness.ml

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,71 @@ let init () =
415415
if not (Sys.file_exists path) then (
416416
Logs.error "witness.yaml.validate: %s not found" path;
417417
Svcomp.errorwith "witness missing"
418-
)
418+
);
419+
let file = !Cilfacade.current_file in
420+
let global_vars =
421+
file.globals
422+
|> List.filter_map (function
423+
| Cil.GVar (v, _, _)
424+
| Cil.GVarDecl (v, _)
425+
| Cil.GFun ({svar = v; _}, _) -> Some (v.vname, Cil.Fv v)
426+
| _ -> None
427+
)
428+
in
429+
let has_global name =
430+
List.exists (function
431+
| Cil.GVar (v, _, _)
432+
| Cil.GVarDecl (v, _)
433+
| Cil.GFun ({svar = v; _}, _) -> String.equal v.vname name
434+
| _ -> false
435+
) file.globals
436+
in
437+
let parse_type (type_: string): Cil.typ option =
438+
try Some (Formatcil.cType type_) with
439+
| exn when GobExn.catch_all_filter exn ->
440+
M.warn_noloc ~category:Witness "ghost variable type parse failed: %s" type_;
441+
None
442+
in
443+
let parse_init (init: string): Cil.exp option =
444+
try Some (Formatcil.cExp init global_vars) with
445+
| exn when GobExn.catch_all_filter exn ->
446+
M.warn_noloc ~category:Witness "ghost variable initializer parse failed: %s" init;
447+
None
448+
in
449+
let instrument_ghost_variable (variable: YamlWitnessType.GhostInstrumentation.Variable.t): unit =
450+
if not (String.equal variable.scope "global") then (
451+
M.warn_noloc ~category:Witness "unsupported ghost variable scope: %s" variable.scope
452+
)
453+
else if has_global variable.name then (
454+
M.error_noloc ~category:Witness "ghost variable already declared in program: %s" variable.name;
455+
Svcomp.errorwith "witness error"
456+
)
457+
else
458+
match parse_type variable.type_, parse_init variable.initial.value with
459+
| Some typ, Some init ->
460+
let v = makeGlobalVar variable.name typ in
461+
let g = GVar (v, {init = SingleInit init}, locUnknown) in
462+
file.globals <- g :: file.globals
463+
| _ ->
464+
M.error_noloc ~category:Witness "failed to instrument ghost variable declaration: %s" variable.name
465+
in
466+
let instrument_ghost_variables yaml_entry =
467+
match YamlWitnessType.Entry.of_yaml yaml_entry with
468+
| Ok {entry_type = YamlWitnessType.EntryType.GhostInstrumentation {ghost_variables; _}; _} ->
469+
List.iter instrument_ghost_variable ghost_variables
470+
| Ok _ ->
471+
()
472+
| Error (`Msg m) ->
473+
M.error_noloc ~category:Witness "couldn't parse entry while extracting ghost instrumentation: %s" m
474+
in
475+
let yaml = match GobResult.Syntax.(Fpath.of_string path >>= Yaml_unix.of_file) with
476+
| Ok yaml -> yaml
477+
| Error (`Msg m) ->
478+
Logs.error "Yaml_unix.of_file: %s" m;
479+
Svcomp.errorwith "witness missing"
480+
in
481+
let yaml_entries = yaml |> GobYaml.list |> BatResult.get_ok in
482+
List.iter instrument_ghost_variables yaml_entries
419483

420484
let loc_of_location (location: YamlWitnessType.Location.t): Cil.location = {
421485
file = location.file_name;

0 commit comments

Comments
 (0)