123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2022 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/>. *)(* *)(****************************************************************************)openMopsaopenFormatmoduleHook=structletname="cpy.count_transitions"typeentry={mutablepy2c:int;mutablec2py:int;}lettable:(Callstack.callstack,entry)Hashtbl.t=Hashtbl.create1letcut_callstackcs=ifcs=[]then[]else[List.hd@@List.revcs]letincr_py2ccs=letcs=cut_callstackcsinletoc=Hashtbl.find_opttablecsinmatchocwith|None->Hashtbl.addtablecs{py2c=1;c2py=0}|Somec->c.py2c<-c.py2c+1letincr_c2pycs=letcs=cut_callstackcsinletoc=Hashtbl.find_opttablecsinmatchocwith|None->Hashtbl.addtablecs{py2c=0;c2py=1}|Somec->c.c2py<-c.c2py+1letinitctx=()letis_cur_bottommanflow=man.lattice.is_bottom(Flow.getT_curman.latticeflow)leton_before_evalroutesemanticexpmanflow=ifis_cur_bottommanflowthen()elsematchekindexpwith|Python.Ast.E_py_call({ekind=Python.Ast.E_py_object({addr_kind=Python.Addr.A_py_c_function(name,uid,kind,oflags,self)},_)},args,kwargs)->incr_py2c(Flow.get_callstackflow)|C.Ast.E_c_builtin_call("PyObject_CallFunction",_)|C.Ast.E_c_builtin_call("PyObject_CallMethod",_)|C.Ast.E_c_builtin_call("PyObject_CallObject",_)->incr_c2py(Flow.get_callstackflow)|_->()leton_after_evalroutesemanticexpmanflowevl=()leton_before_execroutestmtmanflow=()leton_after_execroutestmtmanflowpost=()leton_finishmanflow=letmi,count,ma=Hashtbl.fold(funcsentry(mi,count,ma)->letpy2c,c2py=entry.py2c,entry.c2pyin(* Format.eprintf "%a: %d, %d@." Callstack.pp_callstack_short cs py2c c2py; *)(minmipy2c+c2py,count+py2c+c2py,maxmapy2c+c2py))table(1000000000,0,-1000000000)inFormat.eprintf"min, average, max number of crossings: %d %f %d@."mi(float_of_intcount/.(float_of_int@@Hashtbl.lengthtable))maendlet()=Core.Hook.register_stateless_hook(moduleHook)