123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-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/>. *)(* *)(****************************************************************************)(** Build a domain from a configuration *)openMopsa_utilsopenCore.RouteopenSyntaxopenSig.Combiner.StackedopenSig.Combiner.DomainopenSig.Combiner.StatelessopenSig.Combiner.SimplifiedopenSig.Abstraction.Value(** {2 Values} *)(** ********** *)letrecmake_value(value:value):(moduleVALUE)=matchvaluewith|V_valuev->v|V_unionvalues->Combiners.Value.Union.make(List.mapmake_valuevalues)|V_product(values,reductions)->Combiners.Value.Product.make(List.mapmake_valuevalues)reductions|V_functor(f,vv)->letmoduleF=(valf)in(moduleF.Functor(val(make_valuevv)))(** {2 Simplified domains} *)(** ********************** *)letmake_nonrel_domain(value:value):(moduleSIMPLIFIED_COMBINER)=letmoduleV=(val(make_valuevalue))in(moduleSimplifiedToCombiner(Combiners.Value.Nonrel.Make(V)))letrecis_simplified_domaind=matchd.domain_kindwith|D_simplified_->true|D_nonrel_->true|D_product(dl,_)->List.for_allis_simplified_domaindl|D_functor(F_simplified_,d)->is_simplified_domaind|_->falseletrecmake_simplified_product(domains:domainlist)(reductions:domain_reductionlist):(moduleSIMPLIFIED_COMBINER)=Combiners.Domain.Simplified_product.make(List.mapmake_simplified_domaindomains)~rules:(List.fold_left(funacc->functionDR_simplifiedr->r::acc|_->acc)[]reductions)andmake_simplified_domain_without_semantic(domain:domain):(moduleSIMPLIFIED_COMBINER)=matchdomain.domain_kindwith|D_simplifiedd->(moduleSimplifiedToCombiner(vald))|D_nonrelvalue->make_nonrel_domainvalue|D_product(domains,reductions)->make_simplified_productdomainsreductions|D_functor(F_simplifiedf,d)->letmoduleF=(valf)in(moduleSimplifiedToCombiner(F.Functor(CombinerToSimplified(valmake_simplified_domaind:SIMPLIFIED_COMBINER))))|_->Exceptions.panic"Invalid configuration: %a"pp_domaindomainandmake_simplified_domain(domain:domain):(moduleSIMPLIFIED_COMBINER)=matchdomain.domain_semanticwith|None->make_simplified_domain_without_semanticdomain|Somesemantic->letmoduleD=(val(make_simplified_domain_without_semanticdomain))in(module(structincludeDletsemantics=Core.Semantic.SemanticSet.addsemanticD.semanticsletrouting_table=add_routes(Semanticsemantic)domainsD.routing_tableend):SIMPLIFIED_COMBINER)(** {2 Stateless domains} *)(** ********************** *)letrecis_stateless_domaind=matchd.domain_kindwith|D_stateless_->true|D_switch(dl)->List.for_allis_simplified_domaindl|_->falseletrecmake_stateless_domain_without_semantic(domain:domain):(moduleSTATELESS_COMBINER)=matchdomain.domain_kindwith|D_statelessd->(moduleStatelessToCombiner(vald))|D_switchdl->Combiners.Domain.Stateless_switch.make(List.mapmake_stateless_domaindl)|_->Exceptions.panic"Invalid configuration: %a"pp_domaindomainandmake_stateless_domain(domain:domain):(moduleSTATELESS_COMBINER)=matchdomain.domain_semanticwith|None->make_stateless_domain_without_semanticdomain|Somesemantic->letmoduleD=(val(make_stateless_domain_without_semanticdomain))in(module(structincludeDletsemantics=Core.Semantic.SemanticSet.addsemanticD.semanticsletrouting_table=add_routes(Semanticsemantic)domainsD.routing_tableend):STATELESS_COMBINER)(** {2 Standard domains} *)(** ******************** *)letrecis_standard_domaind=matchd.domain_kindwith|D_domain_->true|D_functor(F_partitioning_,dd)->is_standard_domaindd|D_functor(F_stacked_,dd)->is_standard_domaindd|D_switchdl->List.for_allis_standard_domaindl|_->is_stateless_domaind||is_simplified_domaindletrecmake_standard_domain_without_semantic(domain:domain):(moduleDOMAIN_COMBINER)=ifis_simplified_domaindomainthen(moduleSimplifiedToStandard(val(make_simplified_domaindomain)))elseifis_stateless_domaindomainthen(moduleStatelessToDomain(val(make_stateless_domaindomain)))elseifis_standard_domaindomainthenmatchdomain.domain_kindwith|D_domaind->(moduleDomainToCombiner(vald))|D_functor(F_partitioningf,dd)->letmoduleF=(valf)in(moduleCombiners.Domain.Partitioning.Make(F)(valmake_standard_domaindd:DOMAIN_COMBINER))|D_functor(F_stackeds,dd)->(moduleCombiners.Domain.Apply.Make(valmake_stacked_domains:STACKED_COMBINER)(valmake_standard_domaindd:DOMAIN_COMBINER))|D_switchdomains->Combiners.Domain.Domain_switch.make(List.mapmake_standard_domaindomains)|_->Exceptions.panic"Invalid configuration"else(* Stacked domain *)Exceptions.panic"mk_standard_domain: invalid domain@\n @[%a@]"pp_domaindomainandmake_standard_domain(domain:domain):(moduleDOMAIN_COMBINER)=matchdomain.domain_semanticwith|None->make_standard_domain_without_semanticdomain|Somesemantic->letmoduleD=(val(make_standard_domain_without_semanticdomain))in(module(structincludeDletsemantics=Core.Semantic.SemanticSet.addsemanticD.semanticsletrouting_table=add_routes(Semanticsemantic)domainsD.routing_tableend):DOMAIN_COMBINER)(** {2 Stacked domains} *)(** ******************** *)andprepare_stacked_switch(domains:domainlist):(moduleSTACKED_COMBINER)list=matchdomainswith|[]->[]|{domain_kind=D_stateless_}::_->letrecextract_stateless_prefix=function|[]->[],[]|{domain_kind=D_stateless_}ashd::tl->leta,b=extract_stateless_prefixtlinhd::a,b|l->[],linletl1,l2=extract_stateless_prefixdomainsinlethd=make_stateless_domain(mk_domain(D_switchl1))in(moduleStandardToStacked(StatelessToDomain(valhd)))::prepare_stacked_switchl2|hd::tl->make_stacked_domainhd::prepare_stacked_switchtlandmake_stacked_domain_without_semantic(domain:domain):(moduleSTACKED_COMBINER)=matchdomain.domain_kindwith|D_stackedd->(moduleStackedToCombiner(vald))|D_domaind->(moduleStandardToStacked(DomainToCombiner(vald)))|D_simplifiedd->(moduleStandardToStacked(SimplifiedToStandard(SimplifiedToCombiner(vald))))|D_statelessd->(moduleStandardToStacked(StatelessToDomain(StatelessToCombiner(vald))))|D_nonrel(value)->(moduleStandardToStacked(SimplifiedToStandard(val(make_nonrel_domainvalue))))|D_functor(F_partitioningf,dd)->letmoduleF=(valf)in(moduleStandardToStacked(Combiners.Domain.Partitioning.Make(F)(valmake_standard_domaindd:DOMAIN_COMBINER)))|D_functor(F_stackeds,dd)->(moduleStandardToStacked(Combiners.Domain.Apply.Make(valmake_stacked_domains:STACKED_COMBINER)(valmake_standard_domaindd:DOMAIN_COMBINER)))|D_functor(F_simplifiedf,d)->letmoduleF=(valf)in(moduleStandardToStacked(SimplifiedToStandard(SimplifiedToCombiner(F.Functor(CombinerToSimplified(valmake_simplified_domaind:SIMPLIFIED_COMBINER))))))|D_composedomains->Combiners.Domain.Compose.make(List.mapmake_stacked_domaindomains)|D_switchdomains->Combiners.Domain.Switch.make(prepare_stacked_switchdomains)|D_product(domains,reductions)->ifList.for_allis_simplified_domaindomainsthen(moduleStandardToStacked(SimplifiedToStandard(val(make_simplified_productdomainsreductions))))elseCombiners.Domain.Product.make(List.mapmake_stacked_domaindomains)~eval_rules:(List.fold_left(funacc->functionDR_evalr->r::acc|_->acc)[]reductions)~exec_rules:(List.fold_left(funacc->functionDR_execr->r::acc|_->acc)[]reductions)andmake_stacked_domain(domain:domain):(moduleSTACKED_COMBINER)=matchdomain.domain_semanticwith|None->make_stacked_domain_without_semanticdomain|Somesemantic->letmoduleD=(val(make_stacked_domain_without_semanticdomain))in(module(structincludeDletsemantics=Core.Semantic.SemanticSet.addsemanticD.semanticsletrouting_table=add_routes(Semanticsemantic)domainsD.routing_tableend):STACKED_COMBINER)letfrom_json(domain:domain):(moduleDOMAIN_COMBINER)=letd=make_stacked_domaindomainin(* Add an empty domain below the abstraction to ensure that leave domains
have always a [Below] route *)letmoduleD=(valCombiners.Domain.Compose.make[d;(moduleEmptyDomain)])in(* Translate the stacked domain into a standard domain *)(moduleSig.Combiner.Domain.StackedToStandard(D))