package mopsa
MOPSA: A Modular and Open Platform for Static Analysis using Abstract Interpretation
Install
Dune Dependency
Authors
Maintainers
Sources
mopsa-analyzer-v1.1.tar.gz
md5=fdee20e988343751de440b4f6b67c0f4
sha512=f5cbf1328785d3f5ce40155dada2d95e5de5cce4f084ea30cfb04d1ab10cc9403a26cfb3fa55d0f9da72244482130fdb89c286a9aed0d640bba46b7c00e09500
doc/src/cfg/iterator.ml.html
Source file iterator.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
(****************************************************************************) (* *) (* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *) (* *) (* Copyright (C) 2018-2019 The MOPSA Project. *) (* *) (* This program is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as published *) (* by the Free Software Foundation, either version 3 of the License, or *) (* (at your option) any later version. *) (* *) (* This program is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) (* You should have received a copy of the GNU Lesser General Public License *) (* along with this program. If not, see <http://www.gnu.org/licenses/>. *) (* *) (****************************************************************************) (** General intraprocedural iterator on Control Flow Graphs. *) open Mopsa open Sig.Abstraction.Stateless open Universal.Ast open Ast let name = "cfg.iterators.intraproc" (*==========================================================================*) (** {2 Command line options} *) (*==========================================================================*) let opt_decreasing_iter : int ref = ref 1 (** Number of decreasing iterations after widening stabilisation. *) let () = register_domain_option name { key = "-decreasing-iter"; category = "Loops"; doc = " number of decreasing iterations after stabilization"; spec = Set_int (opt_decreasing_iter, ArgExt.empty); default = "1"; } (*==========================================================================*) (** {2 Iterator} *) (*==========================================================================*) module Domain = struct include GenStatelessDomainId(struct let name = name end) let checks = [] let init prog man flow = None (* flow iterator for CFG *) let cfg_iterator cfg man flow = (* update the node abstract value as the join of incoming edge posts and entries; if weak=true, join with the previous value (for widened nodes) *) let update_node weak flow node = (* post edge flows *) let vs = List.map (fun (port,edge) -> Flow.get (T_cfg_edge_post (CFG.edge_id edge,port)) man.lattice flow ) (CFG.node_in node) in (* entry flow *) let vs = match CFG.node_entry_port cfg.cfg_graph node with | None -> vs | Some port -> (Flow.get (T_cfg_entry port) man.lattice flow)::vs in (* old, if weak *) let nid = CFG.node_id node in let old = Flow.get (T_cfg_node nid) man.lattice flow in let vs = if weak then old::vs else vs in (* join *) let ctx = Flow.get_ctx flow in let v = List.fold_left (man.lattice.join ctx) man.lattice.bottom vs in debug "update node value %a: abs = @[%a@]@." pp_node_as_id node (format man.lattice.print) v; Flow.set (T_cfg_node nid) v man.lattice flow in (* apply a transfer function, update the edge post *) let apply_edge edge flow = let stmt = CFG.edge_data edge in debug "applying edge %a: @[%a@]" pp_edge_as_id edge pp_stmt stmt; let src, dst = CFG.edge_src edge, CFG.edge_dst edge in (* shift source node value into the expected port flow *) let flow = List.fold_left (fun flow (port,node) -> let v = Flow.get (T_cfg_node (CFG.node_id node)) man.lattice flow in debug "input node %a -> port %a, abs = @[%a@]" pp_node_as_id node pp_token port (format man.lattice.print) v; Flow.add port v man.lattice flow ) flow src in (* apply edge transfer function *) man.exec stmt flow >>% fun flow -> (* dispatch flow values into nodes *) let flow = List.fold_left (fun flow (port,_) -> let v = Flow.get port man.lattice flow in debug "edge post %a %a: abs = @[%a@]" pp_edge_as_id edge pp_token port (format man.lattice.print) v; Flow.set (T_cfg_edge_post (CFG.edge_id edge,port)) v man.lattice flow ) flow dst in (* clean-up flows used by transfer function *) let flow = List.fold_left (fun flow (port,_) -> Flow.remove port flow) flow (src@dst) in Post.return flow in (* recompute the node value and call apply_edge for all edges out of this node *) let propagate_node weak node flow = (* update node value *) let flow = update_node weak flow node in (* reompute all edges from this node *) List.fold_left (fun post (_,e) -> post >>% apply_edge e) (Post.return flow) (CFG.node_out node) in (* get the widening node id for a component *) let get_widening_node lst = match lst with | (GraphSig.Simple node)::_ -> CFG.node_id node | _ -> Exceptions.panic "node expected at the head of a component" in (* analyze a component until its head is stable, with widening *) let rec fix_component count lst flow = let wid = get_widening_node lst in let old = Flow.get (T_cfg_node wid) man.lattice flow in debug "analyzing component @[%a@], widen=%a, count=%i, abs=@[%a@]" (Graph.pp_nested_list_list pp_node_as_id) lst pp_node_id wid count (format man.lattice.print) old; (* analyze the component *) analyze_component true lst flow >>% fun flow -> let v = Flow.get (T_cfg_node wid) man.lattice flow in (* check stability *) if man.lattice.subset (Flow.get_ctx flow) v old then ( debug "component head stable %a" pp_node_id wid; refine_component 0 lst flow ) else (* apply widening *) let widened = if count < !Universal.Iterators.Loops.opt_loop_widening_delay then v else man.lattice.widen (Flow.get_ctx flow) old v in debug "component head not stable %a" pp_node_id wid; let flow = Flow.set (T_cfg_node wid) widened man.lattice flow in fix_component (count+1) lst flow (* decreasing iterations *) and refine_component count lst flow = let wid = get_widening_node lst in if count >= !opt_decreasing_iter then ( (* finished *) debug "component analysis finished @[%a@], head=%a, abs=@[%a@]" (Graph.pp_nested_list_list pp_node_as_id) lst pp_node_id wid (format man.lattice.print) (Flow.get (T_cfg_node wid) man.lattice flow); Post.return flow ) else ( (* iter *) debug "decreasing iteration at head %a, count=%i" pp_node_id wid count; analyze_component false lst flow >>% refine_component (count+1) lst ) (* analyze a list of components *) and analyze_component weak lst flow : 'a post = match lst with | (GraphSig.Simple node)::rest -> flow |> propagate_node weak node >>% analyze_component false rest | (GraphSig.Composed l)::rest -> flow |> fix_component 0 l >>% analyze_component false rest | [] -> Post.return flow in (* shift the current flow into the entry *) let flow_in flow = (* set cfg_entry information *) let flow = List.fold_left (fun flow (port,node) -> debug "set entry node %a, port %a" pp_node_as_id node pp_token port; let v = Flow.get port man.lattice flow in Flow.set (T_cfg_entry port) v man.lattice flow ) flow (CFG.entries cfg.cfg_graph) in (* remove cur flow *) Flow.remove T_cur flow in (* gather the flows from the exit nodes *) let flow_out flow = List.fold_left (fun flow (port,node) -> debug "get exit node %a, port %a" pp_node_as_id node pp_token port; let v = Flow.get (T_cfg_node (CFG.node_id node)) man.lattice flow in Flow.add port v man.lattice flow ) flow (CFG.exits cfg.cfg_graph) in (* remove all node-related flows (keeping cur, etc.) *) let cleanup flow = (* clean node info *) let flow = CFG.fold_nodes (fun id _ flow -> Flow.remove (T_cfg_node id) flow) cfg.cfg_graph flow in (* clean edge post info *) let flow = CFG.fold_edges (fun id edge flow -> List.fold_left (fun flow (port,_) -> Flow.remove (T_cfg_edge_post (id,port)) flow ) flow (CFG.edge_dst edge) ) cfg.cfg_graph flow in (* clean entry info *) List.fold_left (fun flow (port,_) -> Flow.remove (T_cfg_entry port) flow) flow (CFG.entries cfg.cfg_graph) in (* all together now *) let flow = flow_in flow in analyze_component false cfg.cfg_order flow >>% fun flow -> let flow = flow |> flow_out |> cleanup in Post.return flow (* atomic test function *) let test_iterator man cond flow = let range = erange cond in debug "CFG test [%a] at %a" pp_expr cond pp_range range; man.eval cond flow >>$ fun cond flow -> man.exec (mk_assume cond range) flow >>% fun tflow -> man.exec (mk_assume (mk_not cond range) range) flow >>% fun fflow -> let tflow = Flow.set T_true (Flow.get T_cur man.lattice tflow) man.lattice tflow and fflow = Flow.set T_false (Flow.get T_cur man.lattice fflow) man.lattice fflow in Flow.join man.lattice tflow fflow |> Post.return let exec stmt man flow = match skind stmt with | S_cfg cfg -> Some (cfg_iterator cfg man flow) | S_test expr -> Some (test_iterator man expr flow) | S_skip -> Some (Post.return flow) | _ -> (* S_expression, S_block and S_print are handled by universal's intraproc *) None let eval exp man flow = None let ask query man flow = None let print_expr man flow printer exp = () end let () = register_stateless_domain (module Domain)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>