Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file senv.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-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). *)(* *)(**************************************************************************)letsolvers=letopenFormula_optionsin[Bitwuzla;Boolector;Z3;CVC4;Yices]letmap=letopenFormula_optionsinletopenSmt_optionsinfunction|Auto|Bitwuzla_builtin|Bitwuzla_legacy|Z3_builtin->assertfalse|Bitwuzla_smtlib->Bitwuzla|Boolector_smtlib->Boolector|Z3_smtlib->Z3|CVC4_smtlib->CVC4|Yices_smtlib->Yicesletget_solver():(moduleSolver.OPEN)=letmoduleLogger=Smt_options.LoggerinmatchSmt_options.SMTSolver.get()with|(Smt_options.Auto|Smt_options.Bitwuzla_builtin)whenOption.is_someLibsolver.bitwuzla_cxx->Logger.debug"Use native Bitwuzla binding (cxx).";letmoduleApi=Api_solver.Make((valOption.getLibsolver.bitwuzla_cxx))in(moduleApi.Open)|Smt_options.Auto|Smt_options.Bitwuzla_builtin|Smt_options.Bitwuzla_legacywhenOption.is_someLibsolver.bitwuzla_c->Logger.debug"Use native Bitwuzla binding (c).";letmoduleApi=Api_solver.Make((valOption.getLibsolver.bitwuzla_c))in(moduleApi.Open)|(Smt_options.Auto|Smt_options.Z3_builtin)whenOption.is_someLibsolver.z3->Logger.debug"Use native z3 binding.";letmoduleApi=Api_solver.SafeArray((valOption.getLibsolver.z3))in(moduleApi.Open)|Auto->(tryletsolver=List.findProver.pingsolversinLogger.info"Found %a in the path."Prover.ppsolver;Formula_options.Solver.setsolver;(moduleSmt2_solver.Solver)withNot_found->Logger.fatal"No SMT solver found.")|Bitwuzla_builtin|Bitwuzla_legacy->Logger.fatal"Native bitwuzla binding is required but not available."|Z3_builtin->Logger.fatal"Native z3 binding is required but not available."|solverwhenProver.ping(mapsolver)->Smt_options.Logger.debug"Found %a in the path."Prover.pp(mapsolver);Formula_options.Solver.set(mapsolver);(moduleSmt2_solver.Solver)|solver->Logger.fatal"%a is required but not available in path."Prover.pp(mapsolver)exceptionUndef=Types.UndefexceptionUninterp=Types.UninterpexceptionUnknown=Types.UnknownexceptionNon_unique=Types.Non_uniqueexceptionNon_mergeable=Types.Non_mergeabletype'atest='aTypes.test=|Trueof'a|Falseof'a|Bothof{t:'a;f:'a}(* utils *)moduleBiMap=Basic_types.BigInt.MapmoduleNiTbl=Basic_types.Int.HtblopenSexprmoduleBiItM=ImapmoduleS=Basic_types.String.MapmoduleI=Basic_types.Int.MapmoduleR=Basic_types.Int.HtblmoduleK=Basic_types.Int.Settype_Types.value+=Term:Sexpr.Expr.tTypes.valuetypelazy_memory=Solver.lazy_memorytype'aTypes.feature+=|VisibleSymbols:Expr.tDba_types.Var.Map.tTypes.feature|VisibleMemory:Memory.tTypes.featuremoduleState(D:Domains.S)(Solver:Solver.GET_MODEL_WITH_STATS)(QS:Types.QUERY_STATISTICS)=structmoduleUid=structtypet=Suid.tletzero=Suid.incrSuid.zero(* zero is reserved for initial memory *)letsucc=Suid.incrletcompare=Suid.compareendmoduleSolver=Solver(QS)letaddr_space=Kernel_options.Machine.word_size()lettimeout=matchFormula_options.Solver.Timeout.get()with|0->None|n->Some(float_of_intn)typet={constraints:Expr.tlist;(* reversed sequence of assertions *)mutabledeps:BvSet.tBvMap.t;mutabledomains:D.tBvMap.t;mutableanchors:K.t;vsymbols:Expr.tI.t;(* collection of visible symbols *)varrays:Memory.tS.t;(* collection of visible arrays *)vmemory:Memory.t;(* visible memory *)lmem:lazy_memory;(* set of lazily initialized memory locations *)model:Model.t;(* a model that satisfy constraints *)}moduleC:Ai.CONTEXTwithtypet=tandtypev:=D.t=structtypenonrect=tletadd_dependencyt~parente=t.deps<-BvMap.adde(BvSet.addparent(tryBvMap.findet.depswithNot_found->BvSet.empty))t.depsletfind_dependencyte=BvMap.findet.depsletaddtev=t.domains<-BvMap.addevt.domainsletfindte=BvMap.findet.domainsendmoduleOverapprox:Memory_manager.CONTEXTwithtypet=tandtypev:=D.t=structincludeAi.Make(D)(C)letanchort(m:Memory.t)=matchmwith|Root|Symbol_->()|Layer{id;_}->t.anchors<-K.addidt.anchorsletanchoredt(m:Memory.t)=matchmwith|Root|Symbol_->true|Layer{id;_}->K.memidt.anchorsendmoduleMMU=Memory_manager.Make(D)(Overapprox)letppppfstate=Model.ppppfstate.modelletempty()={constraints=[];deps=BvMap.empty;domains=BvMap.empty;anchors=K.empty;vsymbols=I.empty;varrays=S.empty;vmemory=Memory.root;lmem={content=BiItM.empty;lemmas=[];addr_space};model=Model.emptyaddr_space;}letalloc~arraystate=letsymbol=Memory.fresharrayin{statewithvarrays=S.addarraysymbolstate.varrays}letassign({id;_}:Types.Var.t)valuestate={statewithvsymbols=I.addidvaluestate.vsymbols}letwrite~addrvaluedirstate=letvmemory=MMU.writestate~addrvaluedirstate.vmemoryin{statewithvmemory}letstorename~addrvaluedirstate=tryletar=S.findnamestate.varraysinletvarrays=S.addname(MMU.writestate~addrvaluedirar)state.varraysin{statewithvarrays}withNot_found->raise_notrace(Uninterpname)letlookup({id;_}asvar:Types.Var.t)t=tryI.findidt.vsymbolswithNot_found->raise_notrace(Undefvar)letread~addrbytesdirstate=letbytes=MMU.readstate~addrbytesdirstate.vmemoryin(bytes,state)letselectname~addrbytesdirstate=tryletarray=S.findnamestate.varraysinletbytes=MMU.readstate~addrbytesdirarrayin(bytes,state)withNot_found->raise_notrace(Uninterpname)letmemcpy~addrlenorigstate=letbase=Bv.value_ofaddrinletlmem={state.lmemwithcontent=BiItM.add~baselen(Bv.value_ofaddr,orig)state.lmem.content;}inletvmemory=MMU.sourcestate~addr:(Expr.constantaddr)~lenorigstate.vmemoryin{statewithlmem;vmemory}letassumecondstate=ifExpr.is_equalcondExpr.onethen(QS.Preprocess.incr_true();Somestate)elseifExpr.is_equalcondExpr.zerothen(QS.Preprocess.incr_false();None)elsematchD.is_zero(Overapprox.evalstatecond)with|True->QS.Preprocess.incr_false();None|False->QS.Preprocess.incr_true();Somestate|Unknown->letconstraints=cond::state.constraintsinifBitvector.zero=Model.evalstate.modelcondthen(QS.Solver.start_timer();letr=Solver.check_sat?timeoutstate.lmemconstraintsinQS.Solver.stop_timer();matchrwith|Unknown->raiseUnknown|Unsat->None|Satmodel->Overapprox.refinestatecondD.one;Some{statewithconstraints;model})else(QS.Preprocess.incr_true();Overapprox.refinestatecondD.one;Some{statewithconstraints})lettestcondstate=ifExpr.is_equalcondExpr.onethen(QS.Preprocess.incr_true();Truestate)elseifExpr.is_equalcondExpr.zerothen(QS.Preprocess.incr_false();Falsestate)elsematchD.is_zero(Overapprox.evalstatecond)with|True->QS.Preprocess.incr_false();Falsestate|False->QS.Preprocess.incr_true();Truestate|Unknown->(lettcons=cond::state.constraintsandfcons=Expr.lognotcond::state.constraintsinlete=Model.evalstate.modelcondinletto_check,constraints=ifBv.is_zeroethen(tcons,fcons)else(fcons,tcons)inQS.Solver.start_timer();letr=Solver.check_sat?timeoutstate.lmemto_checkinQS.Solver.stop_timer();matchrwith|Unknown->raiseUnknown|Unsat->ifBv.is_zeroethen(Overapprox.refinestatecondD.zero;False{statewithconstraints})else(Overapprox.refinestatecondD.one;True{statewithconstraints})|Satmodel->lett,f=ifBv.is_zeroethen({statewithconstraints=to_check;model},{statewithconstraints})else({statewithconstraints},{statewithconstraints=to_check;model})inOverapprox.refinetcondD.one;Overapprox.refinefcondD.zero;Both{t;f})letenumerate=letwith_solverstateenenumexcept=QS.Solver.start_timer();matchSolver.fold_values?timeoutstate.lmemstate.constraintse~n~except(funbvmodelenum->letcond=Expr.equale(Expr.constantbv)inletstate={statewithconstraints=cond::state.constraints;model}inignore(Overapprox.evalstatecond);Overapprox.refinestatecondD.one;(bv,state)::enum)enumwith|exceptionUnknown->QS.Solver.stop_timer();raiseUnknown|enum->QS.Solver.stop_timer();enuminfune?(n=1)?(except=[])state->matchewith|Expr.CstbvwhenList.membvexcept=false->QS.Preprocess.incr_const();[(bv,state)]|Expr.Cst_->QS.Preprocess.incr_const();[]|_->(letbv=Model.evalstate.modeleinletn,enum,except=ifList.membvexceptthen(n,[],except)else(QS.Preprocess.incr_const();letcond=Expr.equale(Expr.constantbv)inletstate={statewithconstraints=cond::state.constraints}inignore(Overapprox.evalstatecond);Overapprox.refinestatecondD.one;(n-1,[(bv,state)],bv::except))inifn=0thenenumelseletsize=Expr.sizeofeandd=Overapprox.evalstateeinmatchD.project~sizedwith|Point_->enum|Top|Seq_->with_solverstateenenumexcept)letmerge~parenttt'=ift==t'thentelseift.lmem==t'.lmemthenmatch(t.constraints,t'.constraints)with|c::constraints,c'::constraints'whenconstraints==constraints'&&Expr.is_equalc(Expr.lognotc')->letdomains=parent.domainsandanchors=K.uniont.anchorst'.anchorsanddeps=BvMap.merge(fun_oo'->match(o,o')with|None,None->assertfalse|None,Some_->o'|Some_,None->o|Somed,Somed'->Some(BvSet.uniondd'))t.depst'.depsandvsymbols=ift.vsymbols==t'.vsymbolsthent.vsymbolselseI.merge(fun_o0o1->match(o0,o1)with|Somee0,Somee1->ifExpr.is_equale0e1theno0elseSome(Expr.itece0e1)|(Some_|None),(Some_|None)->raise_notraceNon_mergeable)t.vsymbolst'.vsymbolsandvarrays=ift.varrays==t'.varraysthent.varrayselseS.merge(fun_o0o1->match(o0,o1)with|Somea0,Somea1->Some(MMU.mergeparentca0a1)|(Some_|None),(Some_|None)->raise_notraceNon_mergeable)t.varrayst'.varraysandvmemory=MMU.mergeparentct.vmemoryt'.vmemoryandlmem=t.lmemandmodel=t.modelin{constraints;deps;domains;anchors;vsymbols;varrays;vmemory;lmem;model;}|_->raise_notraceNon_mergeableelseraise_notraceNon_mergeablemoduleValue=structtypet=Expr.tletkind=Termletconstant=Expr.constantletvaridnamesize=Expr.var(name^Suid.to_stringid)sizenameletunary=Expr.unaryletbinary=Expr.binaryletite=Expr.iteendletassertionst=t.constraintsletget_value(e:Expr.t)_=matchewithCstbv->bv|_->raise_notraceNon_uniqueletget_a_value(e:Expr.t)t=Model.evalt.modeleletpp_smt(target:Expr.tTypes.target)ppft=letmoduleP=Smt2_solver.Printerinletctx=P.create~next_id:Uid.zero()in(* visit assertions *)List.iter(P.visit_blctx)t.constraints;(* visit terms *)letdefs=matchtargetwith|Somedefs->List.iter(fun(e,_)->P.visit_bvctxe)defs;defs|None->P.visit_axctxt.vmemory;List.rev(I.fold(funidexprdefs->matchDba.Var.from_ididwith|exceptionNot_found->defs|{name;_}->P.visit_bvctxexpr;(expr,name)::defs)t.vsymbols[])inFormat.pp_open_vboxppf0;(* print definitions *)P.pp_print_defsppfctx;List.iter(fun(bv,name)->Format.fprintfppf"@[<h>(define-fun %s () (_ BitVec %d)@ "name(Expr.sizeofbv);P.pp_print_bvctxppfbv;Format.fprintfppf")@]@ ")defs;iftarget=NonethenFormat.fprintfppf"@[<h>(define-fun memory () (Array (_ BitVec %d) (_ BitVec 8))@ %a)@]"(Kernel_options.Machine.word_size())(P.pp_print_axctx)t.vmemory;(* print assertions *)List.iter(funbl->Format.pp_open_hboxppf();Format.pp_print_stringppf"(assert ";P.pp_print_blctxppfbl;Format.pp_print_charppf')';Format.pp_close_boxppf();Format.pp_print_spaceppf())t.constraints;Format.pp_close_boxppf()letto_formulat=letmoduleC=Smt2_solver.Crossinletctx=C.create~next_id:Uid.zero()inList.iter(C.assert_blctx)t.constraints;C.define_axctx"memory"t.vmemory;I.iter(funidexpr->C.define_bvctx(Dba.Var.from_idid).nameexpr)t.vsymbols;C.to_formulactxletgetter:typea.aTypes.feature->(t->a)option=function|VisibleSymbols->Some(funstate->I.fold(funidexprmap->matchDba.Var.from_ididwith|exceptionNot_found->map|var->Dba_types.Var.Map.addvarexprmap)state.vsymbolsDba_types.Var.Map.empty)|VisibleMemory->Some(funstate->state.vmemory)|_->Noneletsetter_=NoneendtypeOptions.Engine.t+=Vanilla|Multi_checkslet()=Options.Engine.register"vanilla"Vanilla(fun()->letmoduleSolver=Solver.Once((valget_solver()))in(moduleState(Domains.Interval)(Solver)))let()=Options.Engine.register"multi-checks"Multi_checks(fun()->letmoduleSolver=Solver.MultiChecks((valget_solver()))in(moduleState(Domains.Interval)(Solver)))