2024-05-29 11:47:47 +02:00
|
|
|
|
(*
|
|
|
|
|
Cours "Sémantique et Application à la Vérification de programmes"
|
|
|
|
|
|
|
|
|
|
Antoine Miné 2015
|
|
|
|
|
Marc Chevalier 2018
|
|
|
|
|
Josselin Giet 2021
|
|
|
|
|
Ecole normale supérieure, Paris, France / CNRS / INRIA
|
|
|
|
|
*)
|
|
|
|
|
|
|
|
|
|
open Cfg
|
|
|
|
|
open Domain
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pp_asserts out a =
|
|
|
|
|
ArcSet.iter (fun arc -> match arc.arc_inst with
|
|
|
|
|
| CFG_assert (b, ext) -> Format.fprintf out "%a@ " Errors.pp_err (AssertFalse, ext, b)
|
|
|
|
|
| _ -> failwith "Failed on non-assert") a
|
|
|
|
|
|
|
|
|
|
module Iterator (D : DOMAIN) = struct
|
|
|
|
|
|
2024-05-29 22:30:48 +02:00
|
|
|
|
(*let pp_nodes out (s,nodelist) =
|
2024-05-29 11:47:47 +02:00
|
|
|
|
List.iter (fun node -> (Format.fprintf out "<%i>: %a@ " node.node_id D.print (node_abst node s))) nodelist
|
2024-05-29 22:30:48 +02:00
|
|
|
|
*)
|
2024-05-29 11:47:47 +02:00
|
|
|
|
let iterate cfg =
|
|
|
|
|
let failed_asserts = ref ArcSet.empty in
|
2024-05-29 22:30:48 +02:00
|
|
|
|
|
|
|
|
|
let rec do_fun (f : func) (ctx : D.t) = (*returns an abstraction of the result of exec*)
|
|
|
|
|
let func_state = ref NodeMap.empty in (*avoid losing precision between function calls*)
|
|
|
|
|
let func_dirty = ref NodeSet.empty in begin
|
|
|
|
|
func_state := NodeMap.add f.func_entry ctx (!func_state);
|
2024-05-29 11:47:47 +02:00
|
|
|
|
|
2024-05-29 22:30:48 +02:00
|
|
|
|
let node_abst n = try( NodeMap.find n !func_state )with Not_found -> D.bottom in
|
|
|
|
|
let update_node n s =
|
2024-06-02 12:09:52 +02:00
|
|
|
|
let acctor = if (n.widen_target) then D.widen else D.join in
|
|
|
|
|
func_state := NodeMap.add n (acctor (node_abst n) s) !func_state in
|
2024-05-29 11:47:47 +02:00
|
|
|
|
|
2024-05-29 22:30:48 +02:00
|
|
|
|
let rec iterate n = begin
|
2024-06-01 19:29:10 +02:00
|
|
|
|
(*Format.printf "@[<h 0> Handling node %i@]@ " n.node_id;*)
|
2024-05-29 22:30:48 +02:00
|
|
|
|
func_dirty := NodeSet.remove n !func_dirty;
|
|
|
|
|
let curr_abst = node_abst n in
|
|
|
|
|
let l = List.filter (fun x -> Node.equal x.arc_src n) cfg.cfg_arcs in begin
|
|
|
|
|
List.iter (fun arc -> let s = do_inst curr_abst arc in
|
|
|
|
|
if D.subset s (node_abst arc.arc_dst) then ()
|
2024-06-02 12:09:52 +02:00
|
|
|
|
else (let str = if arc.arc_dst.widen_target then "widen" else "join" in
|
|
|
|
|
Format.printf "@[<h 0>[%i -> %i] Got node %i state %a %s %a " n.node_id arc.arc_dst.node_id arc.arc_dst.node_id
|
|
|
|
|
D.print (node_abst arc.arc_dst)
|
|
|
|
|
str
|
|
|
|
|
D.print s;
|
2024-06-01 21:32:05 +02:00
|
|
|
|
update_node arc.arc_dst s;
|
|
|
|
|
Format.printf "= %a@]@ " D.print (node_abst arc.arc_dst);
|
|
|
|
|
func_dirty := NodeSet.add arc.arc_dst !func_dirty)) l;
|
2024-05-29 22:30:48 +02:00
|
|
|
|
if NodeSet.is_empty !func_dirty then () else
|
|
|
|
|
iterate (NodeSet.choose !func_dirty)
|
|
|
|
|
end end in
|
|
|
|
|
iterate f.func_entry;
|
|
|
|
|
node_abst f.func_exit;
|
|
|
|
|
end
|
|
|
|
|
and do_inst state arc = (* Returns a D.t describing the state we end up in after following the arc. May be bottom*)
|
|
|
|
|
match arc.arc_inst with
|
|
|
|
|
| CFG_skip _-> state
|
|
|
|
|
| CFG_assign (v, iexpr) -> (D.assign state v iexpr)
|
|
|
|
|
| CFG_guard bexpr -> D.guard state bexpr
|
|
|
|
|
| CFG_assert (bexpr, _) -> (let s = D.guard state (CFG_bool_unary (AST_NOT, bexpr)) in
|
|
|
|
|
if D.is_bottom s then (
|
|
|
|
|
Format.printf "State %a is disjoint with %a@ " D.print state Cfg_printer.print_bool_expr (rm_negations (CFG_bool_unary (AST_NOT, bexpr)));
|
|
|
|
|
state) else (
|
|
|
|
|
Format.printf "Failure of guard on %a@ " D.print s;
|
|
|
|
|
failed_asserts := ArcSet.add arc !failed_asserts;
|
|
|
|
|
(D.guard state bexpr)))
|
|
|
|
|
| CFG_call f -> do_fun f state
|
|
|
|
|
in
|
2024-05-29 11:47:47 +02:00
|
|
|
|
begin
|
|
|
|
|
Format.printf "@[<v 0>";
|
2024-05-29 22:30:48 +02:00
|
|
|
|
let init_st = do_fun {func_id = -1; func_name = "_init";
|
|
|
|
|
func_pos = Lexing.dummy_pos, Lexing.dummy_pos;
|
|
|
|
|
func_entry = cfg.cfg_init_entry;
|
|
|
|
|
func_exit = cfg.cfg_init_exit;
|
|
|
|
|
func_args = [];
|
|
|
|
|
func_ret = None;
|
|
|
|
|
func_calls = []} D.init in
|
2024-06-01 19:29:10 +02:00
|
|
|
|
let rec do_main l = match l with
|
|
|
|
|
| x::_ when x.func_name = "main" -> do_fun x init_st
|
|
|
|
|
| _::q -> do_main q
|
|
|
|
|
| [] -> failwith "function main() not found" in
|
|
|
|
|
let _ = do_main cfg.cfg_funcs in
|
2024-05-29 11:47:47 +02:00
|
|
|
|
Format.printf "@]";
|
2024-05-29 22:30:48 +02:00
|
|
|
|
!failed_asserts
|
2024-05-29 11:47:47 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2024-06-01 20:58:56 +02:00
|
|
|
|
open Interval
|
2024-05-29 11:47:47 +02:00
|
|
|
|
open Sign
|
|
|
|
|
open Constant
|
|
|
|
|
open Naked
|
|
|
|
|
open Value_domain
|
|
|
|
|
module ConstIterator = Iterator(NonRelational(AddTopBot(Constants)))
|
|
|
|
|
module SignIterator = Iterator(NonRelational(AddTopBot(Signs)))
|
2024-06-01 20:58:56 +02:00
|
|
|
|
module IntervalIterator = Iterator(NonRelational(AddTopBot(Interval)))
|
2024-05-29 11:47:47 +02:00
|
|
|
|
(*
|
|
|
|
|
let iterate cfg =
|
|
|
|
|
let () = Random.self_init () in
|
|
|
|
|
let iter_arc arc: unit =
|
|
|
|
|
match arc.arc_inst with
|
|
|
|
|
| CFG_assert (b, ext) ->
|
|
|
|
|
Format.printf "%a@ " Errors.pp_err (AssertFalse, ext, b)
|
|
|
|
|
| _ -> () in
|
|
|
|
|
(* let iter_arc arc: unit =
|
|
|
|
|
match arc.arc_inst with
|
|
|
|
|
| CFG_assert (b, ext) ->
|
|
|
|
|
Format.printf "%a@ " Errors.pp_err (AssertFalse, ext, b)
|
|
|
|
|
| _ -> () in
|
|
|
|
|
let iter_node node: unit =
|
|
|
|
|
Format.printf "<%i>: ⊤@ " node.node_id in
|
|
|
|
|
List.iter iter_arc cfg.cfg_arcs;
|
|
|
|
|
Format.printf "Node Values:@ @[<v 0>";
|
|
|
|
|
List.iter iter_node cfg.cfg_nodes;
|
|
|
|
|
Format.printf "@]"*)
|
|
|
|
|
*)
|