[docs]classSuggestions(ExplorationTechnique):""" An exploration technique which analyzes failure cases and logs suggestions for how to mitigate them in future analyses. """
[docs]defstep(self,simgr,stash="active",**kwargs):simgr.step(stash=stash,**kwargs)forstateinsimgr.stashes.get("interrupted",[]):ifid(state)inself.suggested:continueself.suggested.add(id(state))try:event=state.history.events[-1]exceptIndexError:continueifevent.type!="insufficient_resources":continuewithself.lock:# do not interleave logsself.report(state,event)returnsimgr
[docs]@staticmethoddefreport(state,event):ifonce("suggestion_technique"):l.warning("Some of your states hit a resource limit. set logger %s to INFO for suggestions.",__name__)l.info("Create your simulation manager with `suggestions=False` to disable this.")ifevent.objects["type"]isclaripy.errors.ClaripySolverInterruptError:ifevent.objects["reason"][0]=="timeout":limit_number=state.solver._solver.timeoutlimit_kind="hit a solver timeout of %s ms."%limit_numberlimit_minimum=60*1000elifevent.objects["reason"][0]=="max. memory exceeded":limit_number=state.solver._solver.max_memorylimit_kind="hit a solver memory limit of %s MB."%limit_numberlimit_minimum=1024else:limit_number=Nonelimit_kind="hit an unknown resource limit. are you manually mucking with the z3 backend?"limit_minimum=Nonel.info("%s%s",state,limit_kind)iflimit_numberisnotNoneandlimit_minimumisnotNoneandlimit_number<limit_minimum:l.info("The minimum recommended limit is %s. Consider turning it up?",limit_minimum)log=[]forhistoryinstate.history.lineage:forconstraint_eventinhistory.recent_events:ifisinstance(constraint_event,SimActionConstraint):constraint=constraint_event.constraint.astifconstraintishistory.jump_guard:src_addr=history.jump_sourcedst_addr=history.jump_targettransition_type="jumping"else:ifconstraint_event.sim_procedureisNone:src_addr=constraint_event.ins_addrelse:src_addr=constraint_event.sim_procedure.addrblock=state.block(src_addr,num_inst=2)try:dst_addr=block.instruction_addrs[1]exceptIndexError:dst_addr=history.jump_targettransition_type="stepping"iftype(dst_addr)isint:dst_addr=claripy.BVV(dst_addr,state.arch.bits)log.append((constraint,ast_weight(constraint),src_addr,dst_addr,transition_type,len(log)))log.sort(key=lambdat:t[1],reverse=True)max_delta_idx=Noneiflen(log)>1:deltas=[b[1]-a[1]fora,binzip(log,log[1:])]max_delta_idx,max_delta=max(enumerate(deltas))ifmax_delta<2**10:max_delta_idx=Noneifmax_delta_idxisNoneandlogandlog[0][1]>=2**16:formax_delta_idx,tinenumerate(log):ift[1]<2**16:max_delta_idx-=1breakifmax_delta_idxisnotNone:l.info("%d constraint%s abnormally complex.",max_delta_idx+1,"s are"ifmax_delta_idx>0else" is")descriptions=[]fortinsorted(log[:max_delta_idx+1],key=lambdat:t[5]):ifmax_delta_idx<10:l.info("...generated %s from %s to %s",t[4],state.project.loader.describe_addr(t[2]),state.project.loader.describe_addr(t[3].args[0])ift[3].op=="BVV"else"<symbol>",)descriptions.extend(state.solver.describe_variables(t[0]))descriptions=set(descriptions)seen_apis=set()fordescriptionindescriptions:ifdescription[0]=="api":ifdescription[1]notinseen_apis:seen_apis.add(description[1])l.info("...using variables originating in %s (hook it?)",description[1])elifdescription[0]=="mem":if"##mem"notinseen_apis:seen_apis.add("##mem")l.info("...using unconstrained memory (add ZERO_FILL_UNCONSTRAINED_MEMORY?)")elifdescription[0]=="reg":if"##reg"notinseen_apis:seen_apis.add("##reg")l.info("...using unconstrained registers (add ZERO_FILL_UNCONSTRAINED_REGISTERS?)")elifdescription[0]=="file":api="file##"+description[1]ifapinotinseen_apis:seen_apis.add(api)l.info("...using variables from file %s",description[1])else:l.info("...using uncategorized variable %s",description)