123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* 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). *)(* *)(**************************************************************************)openCil_typesopenCil_datatypeopenPdg_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} *)(* ************************************************************************* *)openPdgIndexletget_node_stmtnode=Key.stmt(Pdg.Api.node_keynode)moduleNodeKf=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] *)moduleTodolist:sigtypetodo=private{node:PdgTypes.Node.t;kf:kernel_function;pdg:Pdg.Api.t;callstack_length:int;from_deep:bool}typet=todolistvalmk_init:kernel_function->Pdg.Api.t->PdgTypes.Node.tlist->todolistvaladd:PdgTypes.Node.t->kernel_function->Pdg.Api.t->int->bool->t->tend=structtypetodo={node:PdgTypes.Node.t;kf:kernel_function;pdg:Pdg.Api.t;callstack_length:int;from_deep:bool}typet=todolistletaddnkfpdglenfdlist=matchPdg.Api.node_keynwith|Key.SigKey(Signature.InSignature.InCtrl)->(* do not consider node [InCtrl] *)list|Key.VarDeclviwhennot(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_nodefalse)n(Kernel_function.get_namekf);{node=n;kf=kf;pdg=pdg;callstack_length=len;from_deep=fd}::listletmk_initkfpdg=List.fold_left(funaccn->addnkfpdg0falseacc)[]endmoduleComponent=struct(* not optimal implementation: no memoization (bts#006) *)moduleM=Map.Make(NodeKf)typefwd_kind=Impact|Securitytypekind=|Direct|Indirect_Backward|Forwardoffwd_kindtypevalue={pdg:Pdg.Api.t;mutablecallstack_length:int;mutabledirect:bool;mutableindirect_backward:bool;mutableforward:bool}typet=valueM.tletis_directv=v.directletis_indirect_backwardv=v.indirect_backward&¬v.directletis_forwardv=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. *)letcheck_and_addfirsteltkindpdglen(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;*)letv=M.findeltalreadyinletfound,dir,up,down=matchkindwith|Direct->true,true,false,false|Indirect_Backward->v.indirect_backward,v.direct,true,false|Forward_->v.forward,v.direct,v.indirect_backward,trueinv.callstack_length<-minv.callstack_lengthlen;v.direct<-dir;v.indirect_backward<-up;v.forward<-down;found,alreadywithNot_found->letdir,up,down=matchkindwith|Direct->true,false,false|Indirect_Backward->false,true,false|Forward_->false,false,trueinletv={pdg=pdg;callstack_length=len;direct=dir;indirect_backward=up;forward=down}infalse,iffirst&&kind=ForwardImpactthen(* do not add the initial selected stmt for an impact analysis.
fixed FS#411 *)alreadyelseM.addeltvalreadyletone_step_related_nodeskindpdgnode=(* do not consider address dependencies now (except for impact analysis):
just consider them during the last slicing pass
(for semantic preservation of pointers) *)letdirectnode=Pdg.Api.direct_data_dpdspdgnodeinmatchkindwith|Direct->directnode|Indirect_Backward->directnode@Pdg.Api.direct_ctrl_dpdspdgnode|ForwardSecurity->Pdg.Api.direct_data_usespdgnode@Pdg.Api.direct_ctrl_usespdgnode|ForwardImpact->Pdg.Api.direct_data_usespdgnode@Pdg.Api.direct_ctrl_usespdgnode@Pdg.Api.direct_addr_usespdgnodeletsearch_inputkindkflazy_l=trymatchkindwith|Forward_->Lazy.forcelazy_l|Direct|Indirect_Backward->ifEva.Analysis.use_spec_instead_of_definitionkfthenLazy.forcelazy_lelse[]withNot_found->[]letadd_from_deepcallertodon=Todolist.addncaller(Pdg.Api.getcaller)0truetodoletforward_callerkfnodetodolist=letpdg=Pdg.Api.getkfinList.fold_left(funtodolist(caller,callsites)->(* foreach caller *)List.fold_left(funtodolistcallsite->letnodes=Pdg.Api.find_call_out_nodes_to_selectpdg(PdgTypes.NodeSet.singletonnode)(Pdg.Api.getcaller)callsiteinList.fold_left(add_from_deepcaller)todolistnodes)todolistcallsites)todolist(Eva.Results.callsiteskf)letrelated_nodes_of_nodeskindresultnodes=letinitial_nodes=List.map(funn->n.Todolist.node,n.Todolist.kf)nodesinletrecauxfirstresult=function|[]->result|{Todolist.node=node;kf=kf;pdg=pdg;callstack_length=callstack_length;from_deep=from_deep}::todolist->letelt=node,kfinletfound,result=check_and_addfirsteltkindpdgcallstack_lengthresultinlettodolist=iffoundthenbegintodolistendelsebeginSecurity_slicing_parameters.debug~level:2"considering node %a (in %s)"(Pdg.Api.pretty_nodefalse)node(Kernel_function.get_namekf);(* intraprocedural related_nodes *)letrelated_nodes=one_step_related_nodeskindpdgnodeinSecurity_slicing_parameters.debug~level:3"intraprocedural part done";lettodolist=List.fold_left(funtodon->Todolist.addnkfpdgcallstack_lengthfalsetodo)todolistrelated_nodesin(* interprocedural part *)letbackward_from_deepcompute_nodes=(* [TODO optimisation:]
en fait, regarder from_deep:
si vrai, faire pour chaque caller
sinon, faire uniquement pour le caller d'où on vient *)matchkind,callstack_lengthwith|(Direct|Indirect_Backward),0->(* input of a deep security annotation: foreach call
to [kf], compute its related nodes *)letdo_callertodolist(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;*)letpdg_caller=Pdg.Api.getcallerinletdo_calltodolistcallsite=matchkindwith|Direct|Indirect_Backward->letnodes=compute_nodespdg_callercallsiteinList.fold_left(add_from_deepcaller)todolistnodes|Forward_->todolist(* not considered here, see at end *)inList.fold_leftdo_calltodolistcallsitesinList.fold_leftdo_callertodolist(Eva.Results.callsiteskf)|_->todolistinlettodolist=matchPdg.Api.node_keynodewith|Key.SigKey(Signature.InSignature.InCtrl)->assertfalse|Key.SigKey(Signature.In(Signature.InImplzone))->letcompute_nodespdg_callercallsite=letnodes,_undef_zone=Pdg.Api.find_location_nodes_at_stmtpdg_callercallsite~before:truezone(* TODO : use undef_zone (see FS#201)? *)inletnodes=List.map(fun(n,_z_part)->n)nodesin(* TODO : use _z_part ? *)nodesinbackward_from_deepcompute_nodes|Key.SigKeykey->letcompute_nodespdg_callercallsite=[matchkeywith|Signature.In(Signature.InNumn)->Pdg.Api.find_call_input_nodepdg_callercallsiten|Signature.OutSignature.OutRet->Pdg.Api.find_call_output_nodepdg_callercallsite|Signature.In(Signature.InCtrl|Signature.InImpl_)|Signature.Out_->assertfalse]inbackward_from_deepcompute_nodes|Key.SigCallKey(id,key)->(* the node is a call: search the related nodes inside the
called function (see FS#155) *)iffrom_deepthen(* already come from a deeper annotation:
do not go again inside it *)todolistelseletstmt=Key.call_from_ididinletcalled_kfs=Eva.Results.calleestmtinlettodolist=List.fold_left(funtodolistcalled_kf->(* foreach called kf *)(*Format.printf
"[security] search inside %s (from %s)@."
(Kernel_function.get_name called_kf)
(Kernel_function.get_name kf);*)letcalled_pdg=Pdg.Api.getcalled_kfinletnodes=trymatchkind,keywith|(Direct|Indirect_Backward),Signature.Outout_key->letnodes,_undef_zone=Pdg.Api.find_output_nodescalled_pdgout_key(* TODO: use undef_zone (see FS#201) *)inletnodes=List.map(fun(n,_z_part)->n)nodesin(* TODO : use _z_part ? *)nodes|_,Signature.In(Signature.InNumn)->search_inputkindcalled_kf(lazy[Pdg.Api.find_input_nodecalled_pdgn])|_,Signature.InSignature.InCtrl->search_inputkindcalled_kf(lazy[Pdg.Api.find_entry_point_nodecalled_pdg])|_,Signature.In(Signature.InImpl_)->assertfalse|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_namecalled_kf);[]|Pdg.Api.Bottom|Not_found->assertfalseinList.fold_left(funtodon->(*Format.printf "node %a inside %s@."
(Pdg.Api.pretty_node false) n
(Kernel_function.get_name called_kf);*)Todolist.addncalled_kfcalled_pdg(callstack_length+1)falsetodo)todolistnodes)todolistcalled_kfsin(matchkindwith|Direct|Indirect_Backward->todolist|Forward_->List.fold_left(funtodolistcalled_kf->letcompute_from_stmtfold=fold(fun(n,kfn)_acc->ifKernel_function.equalkfnkfthenn::accelseacc)inletfrom_stmt=compute_from_stmtM.foldresult[]inletfrom_stmt=(* initial nodes may be not in results *)compute_from_stmt(funfeacc->List.fold_left(funacce->fe[]acc)acce)initial_nodesfrom_stmtinletfrom_stmt=List.fold_left(funsn->PdgTypes.NodeSet.addns)PdgTypes.NodeSet.emptyfrom_stmtinletcalled_pdg=Pdg.Api.getcalled_kfinletnodes=tryPdg.Api.find_in_nodes_to_select_for_this_callpdgfrom_stmtstmtcalled_pdgwith|Pdg.Api.Top->(* warning already emitted in the previous fold *)[]|Pdg.Api.Bottom|Not_found->assertfalseinList.fold_left(funtodon->Todolist.addncalled_kfcalled_pdg(callstack_length+1)falsetodo)todolistnodes)todolistcalled_kfs)|Key.CallStmt_|Key.VarDecl_->assertfalse|Key.Stmt_|Key.Label_->todolistin(* [TODO optimisation:] voir commentaire plus haut *)matchkindwith|(Direct|Indirect_Backward)->todolist|Forward_->forward_callerkfnodetodolistendin(* recursive call *)auxfalseresulttodolistinauxtrueresultnodesletinitial_nodeskfstmt=Security_slicing_parameters.debug~level:3"computing initial nodes for %d"stmt.sid;letpdg=Pdg.Api.getkfinletnodes=ifEva.Results.is_reachablestmtthentryPdg.Api.find_simple_stmt_nodespdgstmtwithNot_found->assertfalseelsebeginSecurity_slicing_parameters.debug~level:3"stmt %d is dead. skipping."stmt.sid;[]endinTodolist.mk_initkfpdgnodesletdirectkfstmt=tryletnodes=initial_nodeskfstmtinSecurity_slicing_parameters.debug"computing direct component %d"stmt.sid;letres=related_nodes_of_nodesDirectM.emptynodesin(* add the initial node, fix FS#180 *)letmkp={pdg=p;callstack_length=0;direct=true;indirect_backward=false;forward=false}inletres=List.fold_left(funacc{Todolist.node=n;kf=f;pdg=p}->M.add(n,f)(mkp)acc)resnodesinreswithPdg.Api.Top|Pdg.Api.Bottom->Security_slicing_parameters.warning"PDG is not manageable. skipping.";M.emptyletbackwardkfstmt=tryletnodes=initial_nodeskfstmtinletres=directkfstmtinSecurity_slicing_parameters.debug"computing backward indirect component for %d"stmt.sid;related_nodes_of_nodesIndirect_BackwardresnodeswithPdg.Api.Top|Pdg.Api.Bottom->Security_slicing_parameters.warning"PDG is not manageable. skipping.";M.emptyletwholekfstmt=letres=backwardkfstmtinletfrom=M.fold(fun(n,kf)vacc->Todolist.addnkfv.pdgv.callstack_lengthfalse(*?*)acc)res[]inSecurity_slicing_parameters.debug"computing forward component for stmt %d"stmt.sid;related_nodes_of_nodes(ForwardSecurity)resfrom(* is exactly an impact analysis iff [fwd_kind = Impact] *)letforwardfwd_kindkfstmt=letnodes=initial_nodeskfstmtinSecurity_slicing_parameters.debug"computing forward component for stmt %d"stmt.sid;letres=related_nodes_of_nodes(Forwardfwd_kind)M.emptynodesinletset=M.fold(fun(n,_)_acc->Option.fold~none:acc~some:(funs->Stmt.Set.addsacc)(get_node_stmtn))resStmt.Set.emptyinStmt.Set.elementssetletget_componentkindstmt=letkf=Kernel_function.find_englobing_kfstmtinletaction,check=matchkindwith|Direct->direct,is_direct|Indirect_Backward->backward,is_indirect_backward|Forward_->whole,is_forwardinletset=M.fold(fun(n,_)vacc->ifcheckvthenOption.fold~none:acc~some:(funs->Stmt.Set.addsacc)(get_node_stmtn)elseacc)(actionkfstmt)Stmt.Set.emptyinStmt.Set.elementsset(* 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 *)(* ************************************************************************ *)letregisternamearg=Dynamic.register~plugin:"Security_slicing"name(Datatype.funcStmt.ty(Datatype.listStmt.ty))(Component.get_componentarg)letget_direct_component=register"get_direct_component"Component.Directletget_indirect_backward_component=register"get_indirect_backward_component"Component.Indirect_Backwardletget_forward_component=register"get_forward_component"(Component.ForwardComponent.Security)letimpact_analysis=Dynamic.register~plugin:"Security_slicing""impact_analysis"(Datatype.func2Kernel_function.tyStmt.ty(Datatype.listStmt.ty))(Component.forwardComponent.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:
*)