package frama-c
Platform dedicated to the analysis of source code written in C
Install
Dune Dependency
Authors
-
MMichele Alberti
-
TThibaud Antignac
-
GGergö Barany
-
PPatrick Baudin
-
NNicolas Bellec
-
TThibaut Benjamin
-
AAllan Blanchard
-
LLionel Blatter
-
FFrançois Bobot
-
RRichard Bonichon
-
VVincent Botbol
-
QQuentin Bouillaguet
-
DDavid Bühler
-
ZZakaria Chihani
-
LLoïc Correnson
-
JJulien Crétin
-
PPascal Cuoq
-
ZZaynah Dargaye
-
BBasile Desloges
-
JJean-Christophe Filliâtre
-
PPhilippe Herrmann
-
MMaxime Jacquemin
-
FFlorent Kirchner
-
AAlexander Kogtenkov
-
RRemi Lazarini
-
TTristan Le Gall
-
JJean-Christophe Léchenet
-
MMatthieu Lemerre
-
DDara Ly
-
DDavid Maison
-
CClaude Marché
-
AAndré Maroneze
-
TThibault Martin
-
FFonenantsoa Maurica
-
MMelody Méaulle
-
BBenjamin Monate
-
YYannick Moy
-
PPierre Nigron
-
AAnne Pacalet
-
VValentin Perrelle
-
GGuillaume Petiot
-
DDario Pinto
-
VVirgile Prevosto
-
AArmand Puccetti
-
FFélix Ridoux
-
VVirgile Robles
-
JJan Rochel
-
MMuriel Roger
-
JJulien Signoles
-
NNicolas Stouls
-
KKostyantyn Vorobyov
-
BBoris Yakobowski
Maintainers
Sources
frama-c-29.0-Copper.tar.gz
sha256=d2fbb3b8d0ff83945872e9e6fa258e934a706360e698dae3b4d5f971addf7493
doc/src/frama-c-security_slicing.core/components.ml.html
Source file components.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 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
(**************************************************************************) (* *) (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2024 *) (* CEA (Commissariat à l'énergie atomique et aux énergies *) (* alternatives) *) (* *) (* 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, version 2.1. *) (* *) (* It 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. *) (* *) (* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) open Cil_types open Cil_datatype open Pdg_types (* ************************************************************************* *) (** {2 Searching security annotations} *) (* ************************************************************************* *) (* (** The state of statement for which a security verification should occur. *) module Security_Annotations = Cil_computation.StmtSetRef (struct let name = "Components.Annotations" let dependencies = [ Ast.self ] end) let rec is_security_predicate p = match p.content with | Pand(p1, p2) -> is_security_predicate p1 || is_security_predicate p2 | (* [state(lval) op term] *) Prel(_, { term_node = Tapp(f1, _ , ([ _ ])) }, { term_node = TLval(TVar _,_) }) when f1.l_var_info.lv_name = Model.state_name -> true | (* [state(lval) op term] *) Prel(_, { term_node = Tapp(f1, _, [ _ ]) }, { term_node = _ }) when f1.l_var_info.lv_name = Model.state_name -> assert false | _ -> false let has_security_requirement kf = List.exists (is_security_predicate $ Logic_const.pred_of_id_pred) (Kernel_function.get_spec kf).spec_requires (* Do not called twice. *) let search_security_requirements () = if Security_Annotations.is_empty () then begin Security_slicing_parameters.feedback ~level:3 "searching security annotations"; (* TODO: chercher dans les GlobalAnnotations *) let is_security_annotation a = (match a.annot_content with | AAssert (_behav,p,_) -> is_security_predicate p | AStmtSpec { spec_requires = l } -> List.exists (is_security_predicate $ Logic_const.pred_of_id_pred) l | APragma _ | AInvariant _ (* | ALoopBehavior _ *) (* [JS 2008/02/26] may contain a security predicate *) | AVariant _ | AAssigns _ -> false) in Annotations.iter (fun s annotations -> if Value.is_reachable_stmt s && List.exists (function Before a | After a -> is_security_annotation a) !annotations then Security_Annotations.add s); Globals.Functions.iter (fun kf -> if has_security_requirement kf then List.iter (fun (_, callsites) -> List.iter Security_Annotations.add callsites) (!Value.callers kf)); end *) (* ************************************************************************* *) (** {2 Computing security components} *) (* ************************************************************************* *) open PdgIndex let get_node_stmt node = Key.stmt (Pdg.Api.node_key node) module NodeKf = Datatype.Pair(PdgTypes.Node)(Kernel_function) (* type bwd_kind = Direct | Indirect type fwd_kind = Impact | Security type kind = | Backward of bwd_kind | Forward of fwd_kind (** Debugging purpose only *) let pretty_kind fmt = function | Backward Direct -> Format.fprintf fmt "backward direct" | Backward Indirect -> Format.fprintf fmt "backward indirect" | Forward Security -> Format.fprintf fmt "forward" | Forward Impact -> Format.fprintf fmt "impact" *) (* Never plugged in. To be tested. module Memo : sig val init: kind -> kernel_function -> unit val push_function: stmt -> kernel_function -> unit val pop_function: unit -> unit val memo: Pdg.t_node -> (unit -> (Pdg.t_node * kernel_function) list) -> (Pdg.t_node * kernel_function) list end = struct module Callstack = struct type t = { mutable stack: (stmt * kernel_function) list; mutable current_kf: kernel_function } let init kf callstack = callstack.stack <- []; callstack.current_kf <- kf let push stmt kf stack = stack.stack <- (stmt, stack.current_kf) :: stack.stack; stack.current_kf <- kf let pop stack = let kf = match stack.stack with [] -> assert false | (_, k) :: _ -> k in stack.current_kf <- kf let equal s1 s2 = Kernel_function.equal s1.current_kf s2.current_kf && try List.iter2 (fun (s1, kf1) (s2, kf2) -> if not (s1.sid = s2.sid && Kernel_function.equal kf1 kf2) then raise Exit) s1.stack s2.stack; true with Exit -> false let hash = Hashtbl.hash end (* *********************************************************************** *) (* state: kind -> callstack -> (node * kf) -> (node * kf) list *) module Nodekfs = Hashtbl.Make(NodeKf) (* (node * kf) -> (node * kf) list *) module Callstacks = struct include Hashtbl.Make(Callstack) (* callstack -> nodekfs *) let memo tbl c = try find tbl c with Not_found -> let t = Nodekfs.create 7 in replace tbl c t; t end module Memo = struct include Hashtbl let memo tbl k callstack = try let callstacks = find tbl k in Callstacks.memo callstacks callstack with Not_found -> let callstacks = Callstacks.create 7 in let t = Nodekfs.create 7 in Callstacks.replace callstacks callstack t; replace tbl k callstacks; t end type local_tbl = (Pdg.t_node * kernel_function) list Nodekfs.t type state = { mutable kind: kind; mutable callstack: Callstack.t; mutable local_tbl: local_tbl; memo_tbl: (kind, local_tbl Callstacks.t) Memo.t; } (* *********************************************************************** *) let state = let spec = Cil.empty_funspec () in { kind = Backward Direct; callstack = { Callstack.stack = []; current_kf = { fundec = (* do not use Cil.emptyFunction here since it changes the numbering of variables *) Declaration (spec, Cil_datatype.Varinfo.dummy, None, Cil_datatype.Location.unknown); return_stmt = None; spec = Cil.empty_funspec () } }; local_tbl = Nodekfs.create 0; memo_tbl = Hashtbl.create 5 } let update () = state.local_tbl <- Memo.memo state.memo_tbl state.kind state.callstack let init k kf = state.kind <- k; Callstack.init kf state.callstack; update () let push_function stmt kf = Callstack.push stmt kf state.callstack; update () let pop_function () = Callstack.pop state.callstack; update () let memo node f = let key = node, state.callstack.Callstack.current_kf in try Nodekfs.find state.local_tbl key with Not_found -> let value = f () in Nodekfs.replace state.local_tbl key value; value end *) (* used to enforce an invariant on [add] *) module Todolist : sig type todo = private { node: PdgTypes.Node.t; kf: kernel_function; pdg: Pdg.Api.t; callstack_length: int; from_deep: bool } type t = todo list val mk_init: kernel_function -> Pdg.Api.t -> PdgTypes.Node.t list -> todo list val add: PdgTypes.Node.t -> kernel_function -> Pdg.Api.t -> int -> bool -> t -> t end = struct type todo = { node: PdgTypes.Node.t; kf: kernel_function; pdg: Pdg.Api.t; callstack_length: int; from_deep: bool } type t = todo list let add n kf pdg len fd list = match Pdg.Api.node_key n with | Key.SigKey (Signature.In Signature.InCtrl) -> (* do not consider node [InCtrl] *) list | Key.VarDecl vi when not (Kernel.LibEntry.get () && vi.vglob) -> (* do not consider variable declaration, except if libEntry is set and they are globals (i.e. we could have no further info about them) *) list | _ -> Security_slicing_parameters.debug ~level:2 "adding node %a (in %s)" (Pdg.Api.pretty_node false) n (Kernel_function.get_name kf); { node = n; kf = kf; pdg = pdg; callstack_length = len; from_deep = fd } :: list let mk_init kf pdg = List.fold_left (fun acc n -> add n kf pdg 0 false acc) [] end module Component = struct (* not optimal implementation: no memoization (bts#006) *) module M = Map.Make(NodeKf) type fwd_kind = Impact | Security type kind = | Direct | Indirect_Backward | Forward of fwd_kind type value = { pdg: Pdg.Api.t; mutable callstack_length: int; mutable direct: bool; mutable indirect_backward: bool; mutable forward: bool } type t = value M.t let is_direct v = v.direct let is_indirect_backward v = v.indirect_backward && not v.direct let is_forward v = not (v.direct || v.indirect_backward) (** Returns [found, new_already] with: - [found] is [true] iff [elt] was previously added for [kind] - [new_already] is [already] updated with [elt] and its (new) associated value. *) let check_and_add first elt kind pdg len (already: t) = try (* Format.printf "[security] check node %a (in %s, kind %a)@." (!Pdg.pretty_node true) (fst elt) (Kernel_function.get_name (snd elt)) pretty_kind kind;*) let v = M.find elt already in let found, dir, up, down = match kind with | Direct -> true, true, false, false | Indirect_Backward -> v.indirect_backward, v.direct, true, false | Forward _ -> v.forward, v.direct, v.indirect_backward, true in v.callstack_length <- min v.callstack_length len; v.direct <- dir; v.indirect_backward <- up; v.forward <- down; found, already with Not_found -> let dir, up, down = match kind with | Direct -> true, false, false | Indirect_Backward -> false, true, false | Forward _ -> false, false, true in let v = { pdg = pdg; callstack_length = len; direct = dir; indirect_backward = up; forward = down } in false, if first && kind = Forward Impact then (* do not add the initial selected stmt for an impact analysis. fixed FS#411 *) already else M.add elt v already let kind pdg node = (* do not consider address dependencies now (except for impact analysis): just consider them during the last slicing pass (for semantic preservation of pointers) *) let direct node = Pdg.Api.direct_data_dpds pdg node in match kind with | Direct -> direct node | Indirect_Backward -> direct node @ Pdg.Api.direct_ctrl_dpds pdg node | Forward Security -> Pdg.Api.direct_data_uses pdg node @ Pdg.Api.direct_ctrl_uses pdg node | Forward Impact -> Pdg.Api.direct_data_uses pdg node @ Pdg.Api.direct_ctrl_uses pdg node @ Pdg.Api.direct_addr_uses pdg node let search_input kind kf lazy_l = try match kind with | Forward _ -> Lazy.force lazy_l | Direct | Indirect_Backward -> if Eva.Analysis.use_spec_instead_of_definition kf then Lazy.force lazy_l else [] with Not_found -> [] let add_from_deep caller todo n = Todolist.add n caller (Pdg.Api.get caller) 0 true todo let forward_caller kf node todolist = let pdg = Pdg.Api.get kf in List.fold_left (fun todolist (caller, callsites) -> (* foreach caller *) List.fold_left (fun todolist callsite -> let nodes = Pdg.Api.find_call_out_nodes_to_select pdg (PdgTypes.NodeSet.singleton node) (Pdg.Api.get caller) callsite in List.fold_left (add_from_deep caller) todolist nodes) todolist callsites) todolist (Eva.Results.callsites kf) let kind result nodes = let initial_nodes = List.map (fun n -> n.Todolist.node, n.Todolist.kf) nodes in let rec aux first result = function | [] -> result | { Todolist.node = node; kf = kf; pdg = pdg; callstack_length = callstack_length; from_deep = from_deep } :: todolist -> let elt = node, kf in let found, result = check_and_add first elt kind pdg callstack_length result in let todolist = if found then begin todolist end else begin Security_slicing_parameters.debug ~level:2 "considering node %a (in %s)" (Pdg.Api.pretty_node false) node (Kernel_function.get_name kf); (* intraprocedural related_nodes *) let = one_step_related_nodes kind pdg node in Security_slicing_parameters.debug ~level:3 "intraprocedural part done"; let todolist = List.fold_left (fun todo n -> Todolist.add n kf pdg callstack_length false todo) todolist related_nodes in (* interprocedural part *) let backward_from_deep compute_nodes = (* [TODO optimisation:] en fait, regarder from_deep: si vrai, faire pour chaque caller sinon, faire uniquement pour le caller d'où on vient *) match kind, callstack_length with | (Direct | Indirect_Backward), 0 -> (* input of a deep security annotation: foreach call to [kf], compute its related nodes *) let do_caller todolist (caller, callsites) = (* Format.printf "[security of %s] search callers in %s for zone %a@." (Kernel_function.get_name kf) (Kernel_function.get_name caller) Locations.Zone.pretty zone;*) let pdg_caller = Pdg.Api.get caller in let do_call todolist callsite = match kind with | Direct | Indirect_Backward -> let nodes = compute_nodes pdg_caller callsite in List.fold_left (add_from_deep caller) todolist nodes | Forward _ -> todolist (* not considered here, see at end *) in List.fold_left do_call todolist callsites in List.fold_left do_caller todolist (Eva.Results.callsites kf) | _ -> todolist in let todolist = match Pdg.Api.node_key node with | Key.SigKey (Signature.In Signature.InCtrl) -> assert false | Key.SigKey (Signature.In (Signature.InImpl zone)) -> let compute_nodes pdg_caller callsite = let nodes, _undef_zone = Pdg.Api.find_location_nodes_at_stmt pdg_caller callsite ~before:true zone (* TODO : use undef_zone (see FS#201)? *) in let nodes = List.map (fun (n, _z_part) -> n) nodes in (* TODO : use _z_part ? *) nodes in backward_from_deep compute_nodes | Key.SigKey key -> let compute_nodes pdg_caller callsite = [ match key with | Signature.In (Signature.InNum n) -> Pdg.Api.find_call_input_node pdg_caller callsite n | Signature.Out Signature.OutRet -> Pdg.Api.find_call_output_node pdg_caller callsite | Signature.In (Signature.InCtrl | Signature.InImpl _) | Signature.Out _ -> assert false ] in backward_from_deep compute_nodes | Key.SigCallKey(id, key) -> (* the node is a call: search the related nodes inside the called function (see FS#155) *) if from_deep then (* already come from a deeper annotation: do not go again inside it *) todolist else let stmt = Key.call_from_id id in let called_kfs = Eva.Results.callee stmt in let todolist = List.fold_left (fun todolist called_kf -> (* foreach called kf *) (*Format.printf "[security] search inside %s (from %s)@." (Kernel_function.get_name called_kf) (Kernel_function.get_name kf);*) let called_pdg = Pdg.Api.get called_kf in let nodes = try match kind, key with | (Direct | Indirect_Backward), Signature.Out out_key -> let nodes, _undef_zone = Pdg.Api.find_output_nodes called_pdg out_key (* TODO: use undef_zone (see FS#201) *) in let nodes = List.map (fun (n, _z_part) -> n) nodes in (* TODO : use _z_part ? *) nodes | _, Signature.In (Signature.InNum n) -> search_input kind called_kf (lazy [Pdg.Api.find_input_node called_pdg n]) | _, Signature.In Signature.InCtrl -> search_input kind called_kf (lazy [Pdg.Api.find_entry_point_node called_pdg]) | _, Signature.In (Signature.InImpl _) -> assert false | Forward _, Signature.Out _ -> [] with | Pdg.Api.Top -> Security_slicing_parameters.warning "no precise pdg for function %s. \n\ Ignoring this function in the analysis (potentially incorrect results)." (Kernel_function.get_name called_kf); [] | Pdg.Api.Bottom | Not_found -> assert false in List.fold_left (fun todo n -> (*Format.printf "node %a inside %s@." (Pdg.Api.pretty_node false) n (Kernel_function.get_name called_kf);*) Todolist.add n called_kf called_pdg (callstack_length + 1) false todo) todolist nodes) todolist called_kfs in (match kind with | Direct | Indirect_Backward -> todolist | Forward _ -> List.fold_left (fun todolist called_kf -> let compute_from_stmt fold = fold (fun (n, kfn) _ acc -> if Kernel_function.equal kfn kf then n :: acc else acc) in let from_stmt = compute_from_stmt M.fold result [] in let from_stmt = (* initial nodes may be not in results *) compute_from_stmt (fun f e acc -> List.fold_left (fun acc e -> f e [] acc) acc e) initial_nodes from_stmt in let from_stmt = List.fold_left (fun s n -> PdgTypes.NodeSet.add n s) PdgTypes.NodeSet.empty from_stmt in let called_pdg = Pdg.Api.get called_kf in let nodes = try Pdg.Api.find_in_nodes_to_select_for_this_call pdg from_stmt stmt called_pdg with | Pdg.Api.Top -> (* warning already emitted in the previous fold *) [] | Pdg.Api.Bottom | Not_found -> assert false in List.fold_left (fun todo n -> Todolist.add n called_kf called_pdg (callstack_length + 1) false todo) todolist nodes) todolist called_kfs) | Key.CallStmt _ | Key.VarDecl _ -> assert false | Key.Stmt _ | Key.Label _ -> todolist in (* [TODO optimisation:] voir commentaire plus haut *) match kind with | (Direct | Indirect_Backward) -> todolist | Forward _ -> forward_caller kf node todolist end in (* recursive call *) aux false result todolist in aux true result nodes let initial_nodes kf stmt = Security_slicing_parameters.debug ~level:3 "computing initial nodes for %d" stmt.sid; let pdg = Pdg.Api.get kf in let nodes = if Eva.Results.is_reachable stmt then try Pdg.Api.find_simple_stmt_nodes pdg stmt with Not_found -> assert false else begin Security_slicing_parameters.debug ~level:3 "stmt %d is dead. skipping." stmt.sid; [] end in Todolist.mk_init kf pdg nodes let direct kf stmt = try let nodes = initial_nodes kf stmt in Security_slicing_parameters.debug "computing direct component %d" stmt.sid; let res = related_nodes_of_nodes Direct M.empty nodes in (* add the initial node, fix FS#180 *) let mk p = { pdg = p; callstack_length = 0; direct = true; indirect_backward = false; forward = false } in let res = List.fold_left (fun acc { Todolist.node=n; kf=f; pdg=p } -> M.add (n,f) (mk p) acc) res nodes in res with Pdg.Api.Top | Pdg.Api.Bottom -> Security_slicing_parameters.warning "PDG is not manageable. skipping."; M.empty let backward kf stmt = try let nodes = initial_nodes kf stmt in let res = direct kf stmt in Security_slicing_parameters.debug "computing backward indirect component for %d" stmt.sid; related_nodes_of_nodes Indirect_Backward res nodes with Pdg.Api.Top | Pdg.Api.Bottom -> Security_slicing_parameters.warning "PDG is not manageable. skipping."; M.empty let whole kf stmt = let res = backward kf stmt in let from = M.fold (fun (n,kf) v acc -> Todolist.add n kf v.pdg v.callstack_length false(*?*) acc) res [] in Security_slicing_parameters.debug "computing forward component for stmt %d" stmt.sid; related_nodes_of_nodes (Forward Security) res from (* is exactly an impact analysis iff [fwd_kind = Impact] *) let forward fwd_kind kf stmt = let nodes = initial_nodes kf stmt in Security_slicing_parameters.debug "computing forward component for stmt %d" stmt.sid; let res = related_nodes_of_nodes (Forward fwd_kind) M.empty nodes in let set = M.fold (fun (n,_) _ acc -> Option.fold ~none:acc ~some:(fun s -> Stmt.Set.add s acc) (get_node_stmt n)) res Stmt.Set.empty in Stmt.Set.elements set let get_component kind stmt = let kf = Kernel_function.find_englobing_kf stmt in let action, check = match kind with | Direct -> direct, is_direct | Indirect_Backward -> backward, is_indirect_backward | Forward _ -> whole, is_forward in let set = M.fold (fun (n,_) v acc -> if check v then Option.fold ~none:acc ~some:(fun s -> Stmt.Set.add s acc) (get_node_stmt n) else acc) (action kf stmt) Stmt.Set.empty in Stmt.Set.elements set (* let iter use_ctrl_dpds f kf stmt = let action = if use_ctrl_dpds then whole else direct in M.iter (fun elt _ -> f elt) (action kf stmt) *) end (* ************************************************************************ *) (* Dynamic registration *) (* ************************************************************************ *) let register name arg = Dynamic.register ~plugin:"Security_slicing" name (Datatype.func Stmt.ty (Datatype.list Stmt.ty)) (Component.get_component arg) let get_direct_component = register "get_direct_component" Component.Direct let get_indirect_backward_component = register "get_indirect_backward_component" Component.Indirect_Backward let get_forward_component = register "get_forward_component" (Component.Forward Component.Security) let impact_analysis = Dynamic.register ~plugin:"Security_slicing" "impact_analysis" (Datatype.func2 Kernel_function.ty Stmt.ty (Datatype.list Stmt.ty)) (Component.forward Component.Impact) (* ************************************************************************ *) (* (* type t = stmt *) (** Security component table: a security component is represented by the statement at which a security verification should occur. It is associated with the list of its statements. *) module Components : sig (*val add: t -> stmt -> unit val find: t -> stmt list val self: State.t val fold_fold: ('b -> t -> 'a -> 'b) -> ('a -> Cil_types.stmt -> 'a) -> 'b -> 'a -> 'b *) end = struct module S = State_builder.Hashtbl (Stmt.Hashtbl) (Datatype.Ref(Datatype.List(Stmt))) (struct let name = "Components" let size = 7 let dependencies = [ Ast.self; Eva.Analysis.self ] end) let () = Cmdline.run_after_extended_stage (fun () -> State_dependency_graph.add_codependencies ~onto:S.self [ !Db.Pdg.self ]) (* let add c = let l = S.memo (fun _ -> ref []) c in fun s -> l := s :: !l let find s = !(S.find s) let self = S.self let fold_fold f g init_f init_g = S.fold (fun c l acc -> f acc c (List.fold_left g init_g !l)) init_f *) end module Nodes = State_builder.SetRef (struct include NodeKf.Datatype let compare = NodeKf.compare end) (struct let name = "Components.Nodes" let dependencies = [ Security_Annotations.self ] end) let use_ctrl_dependencies = ref false (** Set tables [Components] and [Stmts]. *) let compute, self = State_builder.apply_once "Components.compute" [ Security_Annotations.self ] (fun () -> search_security_requirements (); let add_component stmt = Security_slicing_parameters.debug "computing security component %d" stmt.sid; let add_one = Components.add stmt in let kf = Kernel_function.find_englobing_kf stmt in Component.iter !use_ctrl_dependencies (fun (n, _ as elt) -> Nodes.add elt; Option.iter add_one (get_node_stmt n)) kf stmt in Security_Annotations.iter add_component) let () = Cmdline.run_after_extended_stage (fun () -> Project.State_builder.add_dependency self !Pdg.self; Project.State_builder.add_dependency Nodes.self self; Project.State_builder.add_dependency Components.self self) let get_component = Dynamic.register "Security.get_component" (Datatype.func Kernel_type.stmt (Datatype.list Kernel_type.stmt)) (fun s -> compute (); Components.find s) (* ************************************************************************ *) (** {2 Security slicing} *) (* ************************************************************************ *) let slice ctrl = use_ctrl_dependencies := ctrl; Security_slicing_parameters.feedback ~level:2 "beginning slicing"; compute (); let name = "security slicing" in let slicing = !Slicing.Project.mk_project name in let select (n, kf) sel = Security_slicing_parameters.debug ~level:2 "selecting %a (of %s)" (Pdg.Api.pretty_node false) n (Kernel_function.get_name kf); !Slicing.Select.select_pdg_nodes sel (!Slicing.Mark.make ~data:true ~addr:true ~ctrl) [ n ] kf in let sel = Nodes.fold select Slicing.Select.empty_selects in Security_slicing_parameters.debug "adding selection"; !Slicing.Request.add_persistent_selection slicing sel; Security_slicing_parameters.debug "applying slicing request"; !Slicing.Request.apply_all_internal slicing; !Slicing.Slice.remove_uncalled slicing; let p = !Slicing.Project.extract name slicing in (* Project.copy ~only:(Options.get_selection_after_slicing ()) p;*) Security_slicing_parameters.feedback ~level:2 "slicing done"; p let slice = Dynamic.register "Security_slicing.slice" (Datatype.func Datatype.bool Project.ty) slice *) (* Local Variables: compile-command: "make -C ../../.." End: *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>