123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)(** Main handler of Universal programs. *)openMopsaopenSig.Abstraction.StatelessopenAstmoduleDomain=structincludeGenStatelessDomainId(structletname="universal.iterators.program"end)letchecks=[]letinitprogmanflow=matchprog.prog_kindwith|P_universalu->set_u_programuflow|>Post.return|>Option.some|_->Noneletevalexpmanflow=Noneletfind_functionffunctions=List.find(function{fun_orig_name}->fun_orig_name=f)functionsletask:typer.('a,r)query->_man->_flow->('a,r)casesoption=funquerymanflow->letget_localsprogcall=letf=find_functioncallprog.universal_fundecsinf.fun_parameters@f.fun_locvars@(matchf.fun_return_varwithNone->[]|Somev->[v])inletopenFramework.Engines.Interactiveinmatchquerywith|Q_defined_variables(Somecall)->letprog=get_u_programflowinCases.singleton(get_localsprogcall)flow|>OptionExt.return|Q_defined_variablesNone->letprog=get_u_programflowinletcs=Flow.get_callstackflowinletglobals=prog.universal_gvarsinletlocals=List.rev@@List.fold_left(funacccall->(get_localsprogcall.Callstack.call_fun_orig_name)@acc)[]csinCases.singleton(globals@locals)flow|>OptionExt.return|Q_allocated_addresses->Cases.singleton[]flow|>OptionExt.return|_->None(** Execute tests in a unit test program *)letexec_testsmainfundecsrangemanflow=(* Execute main body *)man.execmainflow>>%funflow->(* Search for test functions *)lettests=List.filter(funf->letname=f.fun_orig_nameinifString.lengthname<5thenfalseelseString.subname04="test")fundecsin(* Execute tests *)letstmt=mk_stmt(S_unit_tests(tests|>List.map(funf->f.fun_orig_name,mk_expr_stmt(mk_callf[]f.fun_range)range)))rangeinman.execstmtflowletexecstmtmanflow=matchskindstmtwith|S_program({prog_kind=P_universal{universal_main}},_)whennot!Unittest.unittest_flag->man.execuniversal_mainflow|>OptionExt.return|S_program({prog_kind=P_universal{universal_main;universal_fundecs}},_)when!Unittest.unittest_flag->exec_testsuniversal_mainuniversal_fundecsstmt.srangemanflow|>OptionExt.return|_->Noneletprint_exprmanflowprinterexp=()endlet()=register_stateless_domain(moduleDomain)