Skip to content

Commit 58ce3e6

Browse files
authored
Merge pull request #1372 from goblint/fix-locations-pred
Location fixes for YAML witness generation/validation
2 parents 425e3e8 + 27a7518 commit 58ce3e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1098
-624
lines changed

goblint.opam

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ dev-repo: "git+https://github.com/goblint/analyzer.git"
7878
available: os-distribution != "alpine" & arch != "arm64"
7979
pin-depends: [
8080
# published goblint-cil 2.0.3 is currently up-to-date, so no pin needed
81-
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5" ]
81+
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#fb471582d7e9685ab705ba57f7a6675b97ca8f64" ]
8282
# TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252)
8383
[ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ]
8484
]

goblint.opam.locked

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ post-messages: [
134134
pin-depends: [
135135
[
136136
"goblint-cil.2.0.3"
137-
"git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5"
137+
"git+https://github.com/goblint/cil.git#fb471582d7e9685ab705ba57f7a6675b97ca8f64"
138138
]
139139
[
140140
"ppx_deriving.5.2.1"

goblint.opam.template

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
available: os-distribution != "alpine" & arch != "arm64"
44
pin-depends: [
55
# published goblint-cil 2.0.3 is currently up-to-date, so no pin needed
6-
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5" ]
6+
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#fb471582d7e9685ab705ba57f7a6675b97ca8f64" ]
77
# TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252)
88
[ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ]
99
]

src/analyses/unassumeAnalysis.ml

+12-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct
2424

2525
module Locator = WitnessUtil.Locator (Node)
2626

27-
let locator: Locator.t = Locator.create () (* empty default, so don't have to use option everywhere *)
27+
let location_locator: Locator.t = Locator.create () (* empty default, so don't have to use option everywhere *)
2828
let loop_locator: Locator.t = Locator.create () (* empty default, so don't have to use option everywhere *)
2929

3030
type inv = {
@@ -38,26 +38,26 @@ struct
3838
let pre_invs: inv EH.t NH.t = NH.create 100
3939

4040
let init _ =
41-
Locator.clear locator;
41+
Locator.clear location_locator;
4242
Locator.clear loop_locator;
4343
let module FileCfg =
4444
struct
4545
let file = !Cilfacade.current_file
4646
module Cfg = (val !MyCFG.current_cfg)
4747
end in
48-
let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in
48+
let module WitnessInvariant = WitnessUtil.YamlInvariant (FileCfg) in
4949

5050
(* DFS, copied from CfgTools.find_backwards_reachable *)
5151
let reachable = NH.create 100 in
5252
let rec iter_node node =
5353
if not (NH.mem reachable node) then begin
5454
NH.replace reachable node ();
55-
(* TODO: filter synthetic?
56-
See YamlWitness. *)
57-
if WitnessInvariant.is_invariant_node node then
58-
Locator.add locator (Node.location node) node;
59-
if WitnessUtil.NH.mem WitnessInvariant.loop_heads node then
60-
Locator.add loop_locator (Node.location node) node;
55+
Option.iter (fun loc ->
56+
Locator.add location_locator loc node
57+
) (WitnessInvariant.location_location node);
58+
Option.iter (fun loc ->
59+
Locator.add loop_locator loc node
60+
) (WitnessInvariant.loop_location node);
6161
List.iter (fun (_, prev_node) ->
6262
iter_node prev_node
6363
) (FileCfg.Cfg.prev node)
@@ -127,7 +127,7 @@ struct
127127
let inv = location_invariant.location_invariant.string in
128128
let msgLoc: M.Location.t = CilLocation loc in
129129

130-
match Locator.find_opt locator loc with
130+
match Locator.find_opt location_locator loc with
131131
| Some nodes ->
132132
unassume_nodes_invariant ~loc ~nodes inv
133133
| None ->
@@ -190,7 +190,7 @@ struct
190190
let inv = precondition_loop_invariant.loop_invariant.string in
191191
let msgLoc: M.Location.t = CilLocation loc in
192192

193-
match Locator.find_opt locator loc with
193+
match Locator.find_opt loop_locator loc with
194194
| Some nodes ->
195195
unassume_precondition_nodes_invariant ~loc ~nodes pre inv
196196
| None ->
@@ -204,7 +204,7 @@ struct
204204
let inv = location_invariant.value in
205205
let msgLoc: M.Location.t = CilLocation loc in
206206

207-
match Locator.find_opt locator loc with
207+
match Locator.find_opt location_locator loc with
208208
| Some nodes ->
209209
unassume_nodes_invariant ~loc ~nodes inv
210210
| None ->

src/common/framework/cfgTools.ml

+7-15
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,7 @@ let () = Printexc.register_printer (function
132132
| _ -> None (* for other exceptions *)
133133
)
134134

135-
(** Type of CFG "edges": keyed by 'from' and 'to' nodes,
136-
along with the list of connecting instructions. *)
137-
module CfgEdge = struct
138-
type t = Node.t * MyCFG.edges * Node.t [@@deriving eq, hash]
139-
end
140135

141-
module CfgEdgeH = BatHashtbl.Make (CfgEdge)
142136

143137
let createCFG (file: file) =
144138
let cfgF = H.create 113 in
@@ -254,7 +248,7 @@ let createCFG (file: file) =
254248
let pseudo_return = lazy (
255249
if Messages.tracing then Messages.trace "cfg" "adding pseudo-return to the function %s." fd.svar.vname;
256250
let fd_end_loc = {fd_loc with line = fd_loc.endLine; byte = fd_loc.endByte; column = fd_loc.endColumn} in
257-
let newst = mkStmt (Return (None, fd_end_loc)) in
251+
let newst = mkStmt (Return (None, fd_end_loc, locUnknown)) in
258252
newst.sid <- Cilfacade.get_pseudo_return_id fd;
259253
Cilfacade.StmtH.add Cilfacade.pseudo_return_to_fun newst fd;
260254
Cilfacade.IntH.replace Cilfacade.pseudo_return_stmt_sids newst.sid newst;
@@ -340,8 +334,8 @@ let createCFG (file: file) =
340334
(* CIL's xform_switch_stmt (via prepareCFG) always adds both continue and break statements to all Loops. *)
341335
failwith "MyCFG.createCFG: unprepared Loop"
342336

343-
| Return (exp, loc) ->
344-
addEdge (Statement stmt) (loc, Ret (exp, fd)) (Function fd)
337+
| Return (exp, loc, eloc) ->
338+
addEdge (Statement stmt) (Cilfacade.eloc_fallback ~eloc ~loc, Ret (exp, fd)) (Function fd)
345339

346340
| Goto (_, loc) ->
347341
(* Gotos are generally unnecessary and unwanted because find_real_stmt skips over these. *)
@@ -617,7 +611,7 @@ let fprint_hash_dot cfg =
617611
close_out out
618612

619613

620-
let getCFG (file: file) : cfg * cfg * stmt list CfgEdgeH.t =
614+
let getCFG (file: file) : cfg * cfg * _ =
621615
let cfgF, cfgB, skippedByEdge = createCFG file in
622616
let cfgF, cfgB, skippedByEdge =
623617
if get_bool "exp.mincfg" then
@@ -626,13 +620,11 @@ let getCFG (file: file) : cfg * cfg * stmt list CfgEdgeH.t =
626620
(cfgF, cfgB, skippedByEdge)
627621
in
628622
if get_bool "justcfg" then fprint_hash_dot cfgB;
629-
(fun n -> H.find_default cfgF n []), (fun n -> H.find_default cfgB n []), skippedByEdge
623+
(fun n -> H.find_default cfgF n []), (fun n -> H.find_default cfgB n []), (fun u e v -> CfgEdgeH.find skippedByEdge (u, e, v))
630624

631-
let compute_cfg_skips file =
625+
let compute_cfg file =
632626
let cfgF, cfgB, skippedByEdge = getCFG file in
633-
(module struct let prev = cfgB let next = cfgF end : CfgBidir), skippedByEdge
634-
635-
let compute_cfg file = fst (compute_cfg_skips file)
627+
(module struct let prev = cfgB let next = cfgF let skippedByEdge = skippedByEdge end : CfgBidirSkip)
636628

637629

638630
let iter_fd_edges (module Cfg : CfgBackward) fd =

src/common/framework/myCFG.ml

+20-3
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,36 @@ sig
4242
include CfgForward
4343
end
4444

45+
(** Type of CFG "edges": keyed by 'from' and 'to' nodes,
46+
along with the list of connecting instructions. *)
47+
module CfgEdge = struct
48+
type t = Node.t * edges * Node.t [@@deriving eq, hash]
49+
end
50+
51+
module CfgEdgeH = BatHashtbl.Make (CfgEdge)
52+
53+
module type CfgBidirSkip =
54+
sig
55+
include CfgBidir
56+
val skippedByEdge: node -> edges -> node -> stmt list
57+
(** [skippedByEdge from edges to] returns the list of {{!GoblintCil.stmt} AST statements} skipped over by [find_real_stmt] in {!CfgTools.createCfg}.
58+
This consists of statements which do not correspond to CFG nodes, but some surrounding AST constructions. *)
59+
end
60+
4561

4662
module NodeH = BatHashtbl.Make (Node)
4763

4864

4965
let current_node = Node.current_node
50-
let current_cfg : (module CfgBidir) ref =
66+
let current_cfg : (module CfgBidirSkip) ref =
5167
let module Cfg =
5268
struct
5369
let next _ = raise Not_found
5470
let prev _ = raise Not_found
71+
let skippedByEdge _ _ _ = raise Not_found
5572
end
5673
in
57-
ref (module Cfg: CfgBidir)
74+
ref (module Cfg: CfgBidirSkip)
5875

5976
let unknown_exp : exp = mkString "__unknown_value__"
6077
let dummy_func = emptyFunction "__goblint_dummy_init" (* TODO get rid of this? *)
@@ -64,5 +81,5 @@ let dummy_node = FunctionEntry Cil.dummyFunDec
6481
module type FileCfg =
6582
sig
6683
val file: Cil.file
67-
module Cfg: CfgBidir
84+
module Cfg: CfgBidirSkip
6885
end

src/common/util/cilLocation.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ let rec get_stmtLoc stmt: locs =
3434
{loc = locUnknown; eloc = locUnknown}
3535

3636
| Instr (hd :: _) -> get_instrLoc hd
37-
| Return (_, loc) -> {loc; eloc = locUnknown}
37+
| Return (_, loc, eloc) -> {loc; eloc}
3838
| Goto (_, loc) -> {loc; eloc = locUnknown}
3939
| ComputedGoto (_, loc) -> {loc; eloc = locUnknown}
4040
| Break loc -> {loc; eloc = locUnknown}

src/common/util/cilfacade.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ class countFnVisitor = object
494494
inherit nopCilVisitor
495495
method! vstmt s =
496496
match s.skind with
497-
| Return (_, loc)
497+
| Return (_, loc, _)
498498
| Goto (_, loc)
499499
| ComputedGoto (_, loc)
500500
| Break loc

src/common/util/cilfacade0.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ let rec get_stmtLoc stmt =
4242
get_labelsLoc stmt.labels
4343

4444
| Instr (hd :: _) -> get_instrLoc hd
45-
| Return (_, loc) -> loc
45+
| Return (_, loc, eloc) -> eloc_fallback ~eloc ~loc
4646
| Goto (_, loc) -> loc
4747
| ComputedGoto (_, loc) -> loc
4848
| Break loc -> loc

src/framework/control.ml

+21-15
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ let current_node_state_json : (Node.t -> Yojson.Safe.t option) ref = ref (fun _
5454
let current_varquery_global_state_json: (VarQuery.t option -> Yojson.Safe.t) ref = ref (fun _ -> `Null)
5555

5656
(** Given a [Cfg], a [Spec], and an [Inc], computes the solution to [MCP.Path] *)
57-
module AnalyzeCFG (Cfg:CfgBidir) (Spec:Spec) (Inc:Increment) =
57+
module AnalyzeCFG (Cfg:CfgBidirSkip) (Spec:Spec) (Inc:Increment) =
5858
struct
5959

6060
module SpecSys: SpecSys with module Spec = Spec =
@@ -230,7 +230,7 @@ struct
230230
res
231231

232232
(** The main function to preform the selected analyses. *)
233-
let analyze (file: file) (startfuns, exitfuns, otherfuns: Analyses.fundecs) skippedByEdge =
233+
let analyze (file: file) (startfuns, exitfuns, otherfuns: Analyses.fundecs) =
234234
let module FileCfg: FileCfg =
235235
struct
236236
let file = file
@@ -625,13 +625,16 @@ struct
625625
let node_values = LHT.enum lh |> map (Tuple2.map1 fst) in (* drop context from key *)
626626
let hashtbl_size = if fast_count node_values then count node_values else 123 in
627627
let by_loc, by_node = Hashtbl.create hashtbl_size, NodeH.create hashtbl_size in
628-
node_values |> iter (fun (node, v) ->
629-
let loc = Node.location node in
630-
(* join values once for the same location and once for the same node *)
631-
let join = Option.some % function None -> v | Some v' -> Spec.D.join v v' in
632-
Hashtbl.modify_opt loc join by_loc;
633-
NodeH.modify_opt node join by_node;
634-
);
628+
iter (fun (node, v) ->
629+
let loc = match node with
630+
| Statement s -> Cil.get_stmtLoc s.skind (* nosemgrep: cilfacade *) (* Must use CIL's because syntactic search is in CIL. *)
631+
| FunctionEntry _ | Function _ -> Node.location node
632+
in
633+
(* join values once for the same location and once for the same node *)
634+
let join = Option.some % function None -> v | Some v' -> Spec.D.join v v' in
635+
Hashtbl.modify_opt loc join by_loc;
636+
NodeH.modify_opt node join by_node;
637+
) node_values;
635638
by_loc, by_node
636639
in
637640

@@ -656,7 +659,10 @@ struct
656659
let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in
657660

658661
let skipped_statements from_node edge to_node =
659-
CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) []
662+
try
663+
Cfg.skippedByEdge from_node edge to_node
664+
with Not_found ->
665+
[]
660666
in
661667

662668
Transform.run_transformations file active_transformations
@@ -793,22 +799,22 @@ end
793799
[analyze_loop] cannot reside in it anymore since each invocation of
794800
[get_spec] in the loop might/should return a different module, and we
795801
cannot swap the functor parameter from inside [AnalyzeCFG]. *)
796-
let rec analyze_loop (module CFG : CfgBidir) file fs change_info skippedByEdge =
802+
let rec analyze_loop (module CFG : CfgBidirSkip) file fs change_info =
797803
try
798804
let (module Spec) = get_spec () in
799805
let module A = AnalyzeCFG (CFG) (Spec) (struct let increment = change_info end) in
800-
GobConfig.with_immutable_conf (fun () -> A.analyze file fs skippedByEdge)
806+
GobConfig.with_immutable_conf (fun () -> A.analyze file fs)
801807
with Refinement.RestartAnalysis ->
802808
(* Tail-recursively restart the analysis again, when requested.
803809
All solving starts from scratch.
804810
Whoever raised the exception should've modified some global state
805811
to do a more precise analysis next time. *)
806812
(* TODO: do some more incremental refinement and reuse parts of solution *)
807-
analyze_loop (module CFG) file fs change_info skippedByEdge
813+
analyze_loop (module CFG) file fs change_info
808814

809815
(** The main function to perform the selected analyses. *)
810816
let analyze change_info (file: file) fs =
811817
Logs.debug "Generating the control flow graph.";
812-
let (module CFG), skippedByEdge = CfgTools.compute_cfg_skips file in
818+
let (module CFG) = CfgTools.compute_cfg file in
813819
MyCFG.current_cfg := (module CFG);
814-
analyze_loop (module CFG) file fs change_info skippedByEdge
820+
analyze_loop (module CFG) file fs change_info

src/incremental/compareAST.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ let rec eq_stmtkind ?(cfg_comp = false) ((a, af): stmtkind * fundec) ((b, bf): s
339339
let eq_block' = fun x y ~(rename_mapping:rename_mapping) -> if cfg_comp then true, rename_mapping else eq_block (x, af) (y, bf) ~rename_mapping in
340340
match a, b with
341341
| Instr is1, Instr is2 -> forward_list_equal eq_instr is1 is2 ~rename_mapping
342-
| Return (Some exp1, _l1), Return (Some exp2, _l2) -> eq_exp exp1 exp2 ~rename_mapping
343-
| Return (None, _l1), Return (None, _l2) -> true, rename_mapping
342+
| Return (Some exp1, _l1, _el1), Return (Some exp2, _l2, _el2) -> eq_exp exp1 exp2 ~rename_mapping
343+
| Return (None, _l1, _el1), Return (None, _l2, _el2) -> true, rename_mapping
344344
| Return _, Return _ -> false, rename_mapping
345345
| Goto (st1, _l1), Goto (st2, _l2) -> eq_stmt_with_location (!st1, af) (!st2, bf), rename_mapping
346346
| Break _, Break _ -> if cfg_comp then failwith "CompareCFG: Invalid stmtkind in CFG" else true, rename_mapping

src/transform/expressionEvaluation.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct
6868
(* Take all statements *)
6969
|> List.concat_map (fun (f : Cil.fundec) -> f.sallstmts |> List.map (fun s -> f, s))
7070
(* Add locations *)
71-
|> List.map (fun (f, (s : Cil.stmt)) -> (Cilfacade.get_stmtLoc s, f, s))
71+
|> List.map (fun (f, (s : Cil.stmt)) -> (Cil.get_stmtLoc s.skind, f, s)) (* nosemgrep: cilfacade *) (* Must use CIL's because syntactic search is in CIL. *)
7272
(* Filter artificial ones by impossible location *)
7373
|> List.filter (fun ((l : Cil.location), _, _) -> l.line >= 0)
7474
(* Create hash table *)
@@ -109,7 +109,7 @@ struct
109109
fun (s : Cil.stmt) ->
110110
succeeding_statement := Some s;
111111
(* Evaluate at (directly before) a succeeding location *)
112-
Some(self#try_ask (Cilfacade.get_stmtLoc s) expression)
112+
Some(self#try_ask (Cil.get_stmtLoc s.skind) expression) (* nosemgrep: cilfacade *) (* Must use CIL's because syntactic search is in CIL. *)
113113
end
114114
statement.succs
115115
with Not_found -> None

src/util/server.ml

+9-3
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ let serve serv =
121121
|> Seq.map Packet.t_of_yojson
122122
|> Seq.iter (handle_packet serv)
123123

124+
(** Is node valid for lookup by location?
125+
Used for abstract debugging breakpoints. *)
126+
let is_server_node cfgnode =
127+
let loc = UpdateCil.getLoc cfgnode in
128+
not loc.synthetic
129+
124130
let arg_wrapper: (module ArgWrapper) ResettableLazy.t =
125131
ResettableLazy.from_fun (fun () ->
126132
let module Arg = (val (Option.get_exn !ArgTools.current_arg Response.Error.(E (make ~code:RequestFailed ~message:"not analyzed or arg disabled" ())))) in
@@ -133,7 +139,7 @@ let arg_wrapper: (module ArgWrapper) ResettableLazy.t =
133139
Arg.iter_nodes (fun n ->
134140
let cfgnode = Arg.Node.cfgnode n in
135141
let loc = UpdateCil.getLoc cfgnode in
136-
if not loc.synthetic then
142+
if is_server_node cfgnode then
137143
Locator.add locator loc n;
138144
StringH.replace ids (Arg.Node.to_string n) n;
139145
StringH.add cfg_nodes (Node.show_id cfgnode) n (* add for find_all *)
@@ -248,7 +254,7 @@ let node_locator: Locator.t ResettableLazy.t =
248254
if not (NH.mem reachable node) then begin
249255
NH.replace reachable node ();
250256
let loc = UpdateCil.getLoc node in
251-
if not loc.synthetic then
257+
if is_server_node node then
252258
Locator.add locator loc node;
253259
List.iter (fun (_, prev_node) ->
254260
iter_node prev_node
@@ -486,7 +492,7 @@ let () =
486492
let process { fname } serv =
487493
let fundec = Cilfacade.find_name_fundec fname in
488494
let live _ = true in (* TODO: fix this *)
489-
let cfg = CfgTools.sprint_fundec_html_dot !MyCFG.current_cfg live fundec in
495+
let cfg = CfgTools.sprint_fundec_html_dot (module (val !MyCFG.current_cfg: MyCFG.CfgBidirSkip): MyCFG.CfgBidir) live fundec in
490496
{ cfg }
491497
end);
492498

src/witness/svcomp.ml

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ module Specification = SvcompSpec
77

88
module type Task =
99
sig
10-
val file: Cil.file
10+
include MyCFG.FileCfg
1111
val specification: Specification.multi
12-
13-
module Cfg: MyCFG.CfgBidir
1412
end
1513

1614
let task: (module Task) option ref = ref None

0 commit comments

Comments
 (0)