Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | Friends | List of all members
SVF::AbstractInterpretation Class Reference

AbstractInterpretation is same as Abstract Execution. More...

#include <AbstractInterpretation.h>

Public Types

typedef SCCDetection< PTACallGraph * > CallGraphSCC
 

Public Member Functions

 AbstractInterpretation ()
 Constructor.
 
virtual void runOnModule (ICFG *icfg)
 
virtual ~AbstractInterpretation ()
 Destructor.
 
void analyse ()
 Program entry.
 
void addDetector (std::unique_ptr< AEDetector > detector)
 

Static Public Member Functions

static AbstractInterpretationgetAEInstance ()
 

Public Attributes

Set< const CallICFGNode * > checkpoints
 

Private Member Functions

virtual void handleGlobalNode ()
 Global ICFGNode is handled at the entry of the program,.
 
void initWTO ()
 Mark recursive functions in the call graph.
 
bool mergeStatesFromPredecessors (const ICFGNode *icfgNode)
 
bool isBranchFeasible (const IntraCFGEdge *intraEdge, AbstractState &as)
 
virtual void handleSingletonWTO (const ICFGSingletonWTO *icfgSingletonWto)
 handle instructions in svf basic blocks
 
virtual void handleCallSite (const ICFGNode *node)
 
virtual void handleCycleWTO (const ICFGCycleWTO *cycle)
 handle wto cycle (loop)
 
void handleWTOComponents (const std::list< const ICFGWTOComp * > &wtoComps)
 Hanlde two types of WTO components (singleton and cycle)
 
void handleWTOComponent (const ICFGWTOComp *wtoComp)
 
virtual void handleSVFStatement (const SVFStmt *stmt)
 
virtual void SkipRecursiveCall (const CallICFGNode *callnode)
 
bool isCmpBranchFeasible (const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
 
bool isSwitchBranchFeasible (const SVFVar *var, s64_t succ, AbstractState &as)
 
void collectCheckPoint ()
 
void checkPointAllSet ()
 
void updateStateOnAddr (const AddrStmt *addr)
 
void updateStateOnBinary (const BinaryOPStmt *binary)
 
void updateStateOnCmp (const CmpStmt *cmp)
 
void updateStateOnLoad (const LoadStmt *load)
 
void updateStateOnStore (const StoreStmt *store)
 
void updateStateOnCopy (const CopyStmt *copy)
 
void updateStateOnCall (const CallPE *callPE)
 
void updateStateOnRet (const RetPE *retPE)
 
void updateStateOnGep (const GepStmt *gep)
 
void updateStateOnSelect (const SelectStmt *select)
 
void updateStateOnPhi (const PhiStmt *phi)
 
AbstractStategetAbsStateFromTrace (const ICFGNode *node)
 
bool hasAbsStateFromTrace (const ICFGNode *node)
 
AbsExtAPIgetUtils ()
 
virtual bool isExtCall (const CallICFGNode *callNode)
 
virtual void extCallPass (const CallICFGNode *callNode)
 
virtual bool isRecursiveCall (const CallICFGNode *callNode)
 
virtual void recursiveCallPass (const CallICFGNode *callNode)
 
virtual bool isDirectCall (const CallICFGNode *callNode)
 
virtual void directCallFunPass (const CallICFGNode *callNode)
 
virtual bool isIndirectCall (const CallICFGNode *callNode)
 
virtual void indirectCallFunPass (const CallICFGNode *callNode)
 

Private Attributes

SVFIRsvfir
 protected data members, also used in subclasses
 
AEAPIapi {nullptr}
 Execution State, used to store the Interval Value of every SVF variable.
 
ICFGicfg
 
AEStatstat
 
std::vector< const CallICFGNode * > callSiteStack
 
Map< const CallGraphNode *, ICFGWTO * > funcToWTO
 
Set< const CallGraphNode * > recursiveFuns
 
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
 
Map< const ICFGNode *, AbstractStateabstractTrace
 
std::string moduleName
 
std::vector< std::unique_ptr< AEDetector > > detectors
 
AbsExtAPIutils
 
Map< s32_t, s32_t_reverse_predicate
 
Map< s32_t, s32_t_switch_lhsrhs_predicate
 

Friends

class AEStat
 
class AEAPI
 
class BufOverflowDetector
 

Detailed Description

AbstractInterpretation is same as Abstract Execution.

Definition at line 102 of file AbstractInterpretation.h.

Member Typedef Documentation

◆ CallGraphSCC

Definition at line 109 of file AbstractInterpretation.h.

Constructor & Destructor Documentation

◆ AbstractInterpretation()

AbstractInterpretation::AbstractInterpretation ( )

Constructor.

Definition at line 61 of file AbstractInterpretation.cpp.

◆ ~AbstractInterpretation()

AbstractInterpretation::~AbstractInterpretation ( )
virtual

Destructor.

Definition at line 66 of file AbstractInterpretation.cpp.

67{
68 delete stat;
69 for (auto it: funcToWTO)
71
72}
Map< const CallGraphNode *, ICFGWTO * > funcToWTO
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

Member Function Documentation

◆ addDetector()

void SVF::AbstractInterpretation::addDetector ( std::unique_ptr< AEDetector detector)
inline

Definition at line 127 of file AbstractInterpretation.h.

128 {
129 detectors.push_back(std::move(detector));
130 }
std::vector< std::unique_ptr< AEDetector > > detectors

◆ analyse()

void AbstractInterpretation::analyse ( )

Program entry.

Definition at line 103 of file AbstractInterpretation.cpp.

104{
105 initWTO();
106 // handle Global ICFGNode of SVFModule
110 if (const CallGraphNode* cgn = svfir->getCallGraph()->getCallGraphNode("main"))
111 {
113 handleWTOComponents(wto->getWTOComponents());
114 }
115}
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
void initWTO()
Mark recursive functions in the call graph.
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
SVFIR * svfir
protected data members, also used in subclasses
void handleWTOComponents(const std::list< const ICFGWTOComp * > &wtoComps)
Hanlde two types of WTO components (singleton and cycle)
const CallGraphNode * getCallGraphNode(const std::string &name)
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:236
NodeID getBlkPtr() const
Definition IRGraph.h:169
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
CallGraph * getCallGraph()
Definition SVFIR.h:193
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116

◆ checkPointAllSet()

void AbstractInterpretation::checkPointAllSet ( )
private

Definition at line 951 of file AbstractInterpretation.cpp.

952{
953 if (checkpoints.size() == 0)
954 {
955 return;
956 }
957 else
958 {
959 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
960 for (const CallICFGNode* call: checkpoints)
961 SVFUtil::errs() << call->toString() + "\n";
962 assert(false);
963 }
964
965}
Set< const CallICFGNode * > checkpoints
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:77
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56

◆ collectCheckPoint()

void AbstractInterpretation::collectCheckPoint ( )
private

Definition at line 920 of file AbstractInterpretation.cpp.

921{
922 // traverse every ICFGNode
923 Set<std::string> ae_checkpoint_names = {"svf_assert"};
924 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
925
926 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
927 {
928 const ICFGNode* node = it->second;
929 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
930 {
931 if (const SVFFunction *fun = call->getCalledFunction())
932 {
933 if (ae_checkpoint_names.find(fun->getName()) !=
935 {
936 checkpoints.insert(call);
937 }
939 {
940 if (buf_checkpoint_names.find(fun->getName()) !=
942 {
943 checkpoints.insert(call);
944 }
945 }
946 }
947 }
948 }
949}
iterator begin()
Iterators.
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:252
ICFG * getICFG() const
Definition SVFIR.h:172

◆ directCallFunPass()

void AbstractInterpretation::directCallFunPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 618 of file AbstractInterpretation.cpp.

619{
621 callSiteStack.push_back(callNode);
622
624
625 const SVFFunction *callfun =callNode->getCalledFunction();
626 ICFGWTO* wto = funcToWTO[callfun->getCallGraphNode()];
627 handleWTOComponents(wto->getWTOComponents());
628
629 callSiteStack.pop_back();
630 // handle Ret node
631 const RetICFGNode *retNode = callNode->getRetICFGNode();
632 // resume ES to callnode
634}
Map< const ICFGNode *, AbstractState > abstractTrace
std::vector< const CallICFGNode * > callSiteStack

◆ extCallPass()

void AbstractInterpretation::extCallPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 571 of file AbstractInterpretation.cpp.

572{
573 callSiteStack.push_back(callNode);
575 for (auto& detector : detectors)
576 {
577 detector->handleStubFunctions(callNode);
578 }
579 callSiteStack.pop_back();
580}
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.

◆ getAbsStateFromTrace()

AbstractState & SVF::AbstractInterpretation::getAbsStateFromTrace ( const ICFGNode node)
inlineprivate

Definition at line 258 of file AbstractInterpretation.h.

259 {
260 const ICFGNode* repNode = icfg->getRepNode(node);
261 if (abstractTrace.count(repNode) == 0)
262 {
263 assert(0 && "No preAbsTrace for this node");
264 }
265 else
266 {
267 return abstractTrace[repNode];
268 }
269 }
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition ICFG.h:246

◆ getAEInstance()

static AbstractInterpretation & SVF::AbstractInterpretation::getAEInstance ( )
inlinestatic

Definition at line 121 of file AbstractInterpretation.h.

122 {
124 return instance;
125 }

◆ getUtils()

AbsExtAPI * SVF::AbstractInterpretation::getUtils ( )
inlineprivate

Definition at line 277 of file AbstractInterpretation.h.

278 {
279 return utils;
280 }

◆ handleCallSite()

void AbstractInterpretation::handleCallSite ( const ICFGNode node)
privatevirtual

handle call node in ICFGNode

Parameters
nodeICFGNode which has a single CallICFGNode

Definition at line 535 of file AbstractInterpretation.cpp.

536{
537 if (const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node))
538 {
539 if (isExtCall(callNode))
540 {
542 }
543 else if (isRecursiveCall(callNode))
544 {
546 }
547 else if (isDirectCall(callNode))
548 {
550 }
551 else if (isIndirectCall(callNode))
552 {
554 }
555 else
556 {
557 assert(false && "implement this part");
558 }
559 }
560 else
561 {
562 assert (false && "it is not call node");
563 }
564}
virtual bool isRecursiveCall(const CallICFGNode *callNode)
virtual void recursiveCallPass(const CallICFGNode *callNode)
virtual bool isDirectCall(const CallICFGNode *callNode)
virtual void extCallPass(const CallICFGNode *callNode)
virtual void directCallFunPass(const CallICFGNode *callNode)
virtual bool isExtCall(const CallICFGNode *callNode)
virtual bool isIndirectCall(const CallICFGNode *callNode)
virtual void indirectCallFunPass(const CallICFGNode *callNode)

◆ handleCycleWTO()

void AbstractInterpretation::handleCycleWTO ( const ICFGCycleWTO cycle)
privatevirtual

handle wto cycle (loop)

handle wto cycle (loop)

Parameters
cycleWTOCycle which has weak topo order of basic blocks and nested cycles

Definition at line 672 of file AbstractInterpretation.cpp.

673{
674 const ICFGNode* cycle_head = cycle->head()->getICFGNode();
675 // Flag to indicate if we are in the increasing phase
676 bool increasing = true;
677 // Infinite loop until a fixpoint is reached,
678 for (u32_t cur_iter = 0;; cur_iter++)
679 {
680 // Start widening or narrowing if cur_iter >= widen threshold (widen delay)
682 {
683 // Widen or narrow after processing cycle head node
685 handleWTOComponent(cycle->head());
687 if (increasing)
688 {
689 // Widening phase
692 {
693 increasing = false;
694 continue;
695 }
696 }
697 else
698 {
699 // Widening's fixpoint reached in the widening phase, switch to narrowing
702 {
703 // Narrowing's fixpoint reached in the narrowing phase, exit loop
704 break;
705 }
706 }
707 }
708 else
709 {
710 // Handle the cycle head
711 handleSingletonWTO(cycle->head());
712 }
713 // Handle the cycle body
714 handleWTOComponents(cycle->getWTOComponents());
715 }
716}
unsigned u32_t
Definition CommandLine.h:18
void handleWTOComponent(const ICFGWTOComp *wtoComp)
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto)
handle instructions in svf basic blocks
AbstractState narrowing(const AbstractState &other)
domain narrow with other, and return the narrowed domain
AbstractState widening(const AbstractState &other)
domain widen with other, and return the widened domain
static const Option< u32_t > WidenDelay
Definition Options.h:246

◆ handleGlobalNode()

void AbstractInterpretation::handleGlobalNode ( )
privatevirtual

Global ICFGNode is handled at the entry of the program,.

handle global node

Definition at line 118 of file AbstractInterpretation.cpp.

119{
120 const ICFGNode* node = icfg->getGlobalICFGNode();
123 // Global Node, we just need to handle addr, load, store, copy and gep
124 for (const SVFStmt *stmt: node->getSVFStmts())
125 {
127 }
128}
virtual void handleSVFStatement(const SVFStmt *stmt)

◆ handleSingletonWTO()

void AbstractInterpretation::handleSingletonWTO ( const ICFGSingletonWTO icfgSingletonWto)
privatevirtual

handle instructions in svf basic blocks

handle instructions in ICFGSingletonWTO

Parameters
blockbasic block that has one instruction or a series of instructions

Definition at line 476 of file AbstractInterpretation.cpp.

477{
478 const ICFGNode* node = icfgSingletonWto->getICFGNode();
479 stat->getBlockTrace()++;
480
481 std::deque<const ICFGNode*> worklist;
482
483 const std::vector<const ICFGNode*>& worklist_vec = icfg->getSubNodes(node);
484 for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
485 {
486 const ICFGNode* curNode = *it;
488 // handle SVF Stmt
489 for (const SVFStmt *stmt: curNode->getSVFStmts())
490 {
492 }
493 // inlining the callee by calling handleFunc for the callee function
494 if (const CallICFGNode* callnode = SVFUtil::dyn_cast<CallICFGNode>(curNode))
495 {
497 }
498 for (auto& detector: detectors)
499 detector->detect(getAbsStateFromTrace(node), node);
501 }
502}
virtual void handleCallSite(const ICFGNode *node)
const std::vector< const ICFGNode * > & getSubNodes(const ICFGNode *node) const
Definition ICFG.h:241

◆ handleSVFStatement()

void AbstractInterpretation::handleSVFStatement ( const SVFStmt stmt)
privatevirtual

handle SVF Statement like CmpStmt, CallStmt, GepStmt, LoadStmt, StoreStmt, etc.

Parameters
stmtSVFStatement which is a value flow of instruction

Definition at line 718 of file AbstractInterpretation.cpp.

719{
720 if (const AddrStmt *addr = SVFUtil::dyn_cast<AddrStmt>(stmt))
721 {
723 }
724 else if (const BinaryOPStmt *binary = SVFUtil::dyn_cast<BinaryOPStmt>(stmt))
725 {
727 }
728 else if (const CmpStmt *cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
729 {
731 }
732 else if (SVFUtil::isa<UnaryOPStmt>(stmt))
733 {
734 }
735 else if (SVFUtil::isa<BranchStmt>(stmt))
736 {
737 // branch stmt is handled in hasBranchES
738 }
739 else if (const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(stmt))
740 {
741 updateStateOnLoad(load);
742 }
743 else if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
744 {
745 updateStateOnStore(store);
746 }
747 else if (const CopyStmt *copy = SVFUtil::dyn_cast<CopyStmt>(stmt))
748 {
750 }
751 else if (const GepStmt *gep = SVFUtil::dyn_cast<GepStmt>(stmt))
752 {
754 }
755 else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt))
756 {
758 }
759 else if (const PhiStmt *phi = SVFUtil::dyn_cast<PhiStmt>(stmt))
760 {
762 }
763 else if (const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
764 {
765 // To handle Call Edge
767 }
768 else if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
769 {
770 updateStateOnRet(retPE);
771 }
772 else
773 assert(false && "implement this part");
774}
copy
Definition cJSON.cpp:414
void updateStateOnCall(const CallPE *callPE)
void updateStateOnStore(const StoreStmt *store)
void updateStateOnGep(const GepStmt *gep)
void updateStateOnPhi(const PhiStmt *phi)
void updateStateOnSelect(const SelectStmt *select)
void updateStateOnAddr(const AddrStmt *addr)
void updateStateOnRet(const RetPE *retPE)
void updateStateOnCopy(const CopyStmt *copy)
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
void updateStateOnCmp(const CmpStmt *cmp)

◆ handleWTOComponent()

void AbstractInterpretation::handleWTOComponent ( const ICFGWTOComp wtoComp)
private

Definition at line 515 of file AbstractInterpretation.cpp.

516{
517 if (const ICFGSingletonWTO* node = SVFUtil::dyn_cast<ICFGSingletonWTO>(wtoNode))
518 {
519 if (mergeStatesFromPredecessors(node->getICFGNode()))
520 handleSingletonWTO(node);
521 }
522 // Handle WTO cycles
523 else if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(wtoNode))
524 {
525 if (mergeStatesFromPredecessors(cycle->head()->getICFGNode()))
527 }
528 // Assert false for unknown WTO types
529 else
530 {
531 assert(false && "unknown WTO type!");
532 }
533}
virtual void handleCycleWTO(const ICFGCycleWTO *cycle)
handle wto cycle (loop)
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)

◆ handleWTOComponents()

void AbstractInterpretation::handleWTOComponents ( const std::list< const ICFGWTOComp * > &  wtoComps)
private

Hanlde two types of WTO components (singleton and cycle)

Definition at line 507 of file AbstractInterpretation.cpp.

508{
509 for (const ICFGWTOComp* wtoNode : wtoComps)
510 {
512 }
513}

◆ hasAbsStateFromTrace()

bool SVF::AbstractInterpretation::hasAbsStateFromTrace ( const ICFGNode node)
inlineprivate

Definition at line 271 of file AbstractInterpretation.h.

272 {
273 const ICFGNode* repNode = icfg->getRepNode(node);
274 return abstractTrace.count(repNode) != 0;
275 }

◆ indirectCallFunPass()

void AbstractInterpretation::indirectCallFunPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 642 of file AbstractInterpretation.cpp.

643{
647 if (!as.inVarToAddrsTable(call_id))
648 {
649 return;
650 }
654 if(const FunObjVar*funObjVar = SVFUtil::dyn_cast<FunObjVar>(func_var))
655 {
656 const CallGraphNode* callfun = funObjVar->getCallGraphNode();
657 callSiteStack.push_back(callNode);
659
661 handleWTOComponents(wto->getWTOComponents());
662 callSiteStack.pop_back();
663 // handle Ret node
664 const RetICFGNode* retNode = callNode->getRetICFGNode();
666 }
667}
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
AddressValue & getAddrs()
AddrSet::const_iterator begin() const
NodeType * getGNode(NodeID id) const
Get a node.
const CallSiteToFunPtrMap & getIndirectCallsites() const
Add/get indirect callsites.
Definition SVFIR.h:351
u32_t NodeID
Definition GeneralType.h:55

◆ initWTO()

void AbstractInterpretation::initWTO ( )
private

Mark recursive functions in the call graph.

This function identifies and marks recursive functions in the call graph. It does this by detecting cycles in the call graph's strongly connected components (SCC). Any function found to be part of a cycle is marked as recursive.

Definition at line 81 of file AbstractInterpretation.cpp.

82{
84 // Detect if the call graph has cycles by finding its strongly connected components (SCC)
86 callGraphScc->find();
88
89 // Iterate through the call graph
90 for (auto it = svfirCallGraph->begin(); it != svfirCallGraph->end(); it++)
91 {
92 // Check if the current function is part of a cycle
93 if (callGraphScc->isInCycle(it->second->getId()))
94 recursiveFuns.insert(it->second); // Mark the function as recursive
95 if (it->second->getFunction()->isDeclaration())
96 continue;
97 auto* wto = new ICFGWTO(icfg, icfg->getFunEntryICFGNode(it->second->getFunction()));
98 wto->init();
99 funcToWTO[it->second] = wto;
100 }
101}
Set< const CallGraphNode * > recursiveFuns
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition Andersen.h:408
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition ICFG.cpp:234
SCCDetection< PTACallGraph * > CallGraphSCC
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.

◆ isBranchFeasible()

bool AbstractInterpretation::isBranchFeasible ( const IntraCFGEdge intraEdge,
AbstractState as 
)
private

Check if execution state exist at the branch edge

Parameters
intraEdgethe edge from CmpStmt to the next node
Returns
if this edge is feasible

Definition at line 448 of file AbstractInterpretation.cpp.

450{
451 const SVFVar *cmpVar = intraEdge->getCondition();
452 if (cmpVar->getInEdges().empty())
453 {
455 intraEdge->getSuccessorCondValue(), as);
456 }
457 else
458 {
459 assert(!cmpVar->getInEdges().empty() &&
460 "no in edges?");
461 SVFStmt *cmpVarInStmt = *cmpVar->getInEdges().begin();
462 if (const CmpStmt *cmpStmt = SVFUtil::dyn_cast<CmpStmt>(cmpVarInStmt))
463 {
465 intraEdge->getSuccessorCondValue(), as);
466 }
467 else
468 {
470 cmpVar, intraEdge->getSuccessorCondValue(), as);
471 }
472 }
473 return true;
474}
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)

◆ isCmpBranchFeasible()

bool AbstractInterpretation::isCmpBranchFeasible ( const CmpStmt cmpStmt,
s64_t  succ,
AbstractState as 
)
private

Check if this cmpStmt and succ are satisfiable to the execution state.

Parameters
cmpStmtCmpStmt is a conditional branch statement
succthe value of cmpStmt (True or False)
Returns
if this ICFGNode has preceding execution state

Definition at line 183 of file AbstractInterpretation.cpp.

185{
187 // get cmp stmt's op0, op1, and predicate
188 NodeID op0 = cmpStmt->getOpVarID(0);
189 NodeID op1 = cmpStmt->getOpVarID(1);
190 NodeID res_id = cmpStmt->getResID();
191 s32_t predicate = cmpStmt->getPredicate();
192
193 // if op0 or op1 is undefined, return;
194 // skip address compare
195 if (new_es.inVarToAddrsTable(op0) || new_es.inVarToAddrsTable(op1))
196 {
197 as = new_es;
198 return true;
199 }
200 const LoadStmt *load_op0 = nullptr;
201 const LoadStmt *load_op1 = nullptr;
202 // get '%1 = load i32 s', and load inst may not exist
204 if (!loadVar0->getInEdges().empty())
205 {
206 SVFStmt *loadVar0InStmt = *loadVar0->getInEdges().begin();
207 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt))
208 {
210 }
211 else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar0InStmt))
212 {
213 loadVar0 = svfir->getGNode(copyStmt->getRHSVarID());
214 if (!loadVar0->getInEdges().empty())
215 {
216 SVFStmt *loadVar0InStmt2 = *loadVar0->getInEdges().begin();
217 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt2))
218 {
220 }
221 }
222 }
223 }
224
226 if (!loadVar1->getInEdges().empty())
227 {
228 SVFStmt *loadVar1InStmt = *loadVar1->getInEdges().begin();
229 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt))
230 {
232 }
233 else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar1InStmt))
234 {
235 loadVar1 = svfir->getGNode(copyStmt->getRHSVarID());
236 if (!loadVar1->getInEdges().empty())
237 {
238 SVFStmt *loadVar1InStmt2 = *loadVar1->getInEdges().begin();
239 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt2))
240 {
242 }
243 }
244 }
245 }
246 // for const X const, we may get concrete resVal instantly
247 // for var X const, we may get [0,1] if the intersection of var and const is not empty set
248 IntervalValue resVal = new_es[res_id].getInterval();
250 // If Var X const generates bottom value, it means this branch path is not feasible.
251 if (resVal.isBottom())
252 {
253 return false;
254 }
255
256 bool b0 = new_es[op0].getInterval().is_numeral();
257 bool b1 = new_es[op1].getInterval().is_numeral();
258
259 // if const X var, we should reverse op0 and op1.
260 if (b0 && !b1)
261 {
262 std::swap(op0, op1);
263 std::swap(load_op0, load_op1);
264 predicate = _switch_lhsrhs_predicate[predicate];
265 }
266 else
267 {
268 // if var X var, we cannot preset the branch condition to infer the intervals of var0,var1
269 if (!b0 && !b1)
270 {
271 as = new_es;
272 return true;
273 }
274 // if const X const, we can instantly get the resVal
275 else if (b0 && b1)
276 {
277 as = new_es;
278 return true;
279 }
280 }
281 // if cmp is 'var X const == false', we should reverse predicate 'var X' const == true'
282 // X' is reverse predicate of X
283 if (succ == 0)
284 {
285 predicate = _reverse_predicate[predicate];
286 }
287 else {}
288 // change interval range according to the compare predicate
289 AddressValue addrs;
290 if(load_op0 && new_es.inVarToAddrsTable(load_op0->getRHSVarID()))
291 addrs = new_es[load_op0->getRHSVarID()].getAddrs();
292
293 IntervalValue &lhs = new_es[op0].getInterval(), &rhs = new_es[op1].getInterval();
294 switch (predicate)
295 {
299 {
300 // Var == Const, so [var.lb, var.ub].meet_with(const)
302 // if lhs is register value, we should also change its mem obj
303 for (const auto &addr: addrs)
304 {
305 NodeID objId = new_es.getInternalID(addr);
306 if (new_es.inAddrToValTable(objId))
307 {
308 new_es.load(addr).meet_with(rhs);
309 }
310 }
311 break;
312 }
316 // Compliment set
317 break;
322 // Var > Const, so [var.lb, var.ub].meet_with([Const+1, +INF])
323 lhs.meet_with(IntervalValue(rhs.lb() + 1, IntervalValue::plus_infinity()));
324 // if lhs is register value, we should also change its mem obj
325 for (const auto &addr: addrs)
326 {
327 NodeID objId = new_es.getInternalID(addr);
328 if (new_es.inAddrToValTable(objId))
329 {
330 new_es.load(addr).meet_with(
332 }
333 }
334 break;
339 {
340 // Var >= Const, so [var.lb, var.ub].meet_with([Const, +INF])
342 // if lhs is register value, we should also change its mem obj
343 for (const auto &addr: addrs)
344 {
345 NodeID objId = new_es.getInternalID(addr);
346 if (new_es.inAddrToValTable(objId))
347 {
348 new_es.load(addr).meet_with(
350 }
351 }
352 break;
353 }
358 {
359 // Var < Const, so [var.lb, var.ub].meet_with([-INF, const.ub-1])
360 lhs.meet_with(IntervalValue(IntervalValue::minus_infinity(), rhs.ub() - 1));
361 // if lhs is register value, we should also change its mem obj
362 for (const auto &addr: addrs)
363 {
364 NodeID objId = new_es.getInternalID(addr);
365 if (new_es.inAddrToValTable(objId))
366 {
367 new_es.load(addr).meet_with(
369 }
370 }
371 break;
372 }
377 {
378 // Var <= Const, so [var.lb, var.ub].meet_with([-INF, const.ub])
380 // if lhs is register value, we should also change its mem obj
381 for (const auto &addr: addrs)
382 {
383 NodeID objId = new_es.getInternalID(addr);
384 if (new_es.inAddrToValTable(objId))
385 {
386 new_es.load(addr).meet_with(
388 }
389 }
390 break;
391 }
393 break;
395 break;
396 default:
397 assert(false && "implement this part");
398 abort();
399 }
400 as = new_es;
401 return true;
402}
Map< s32_t, s32_t > _switch_lhsrhs_predicate
@ ICMP_SGT
signed greater than
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_UGE
unsigned greater or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_NE
not equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_ULT
unsigned less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ ICMP_SLT
signed less than
@ ICMP_UGT
unsigned greater than
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
static BoundedInt minus_infinity()
Get minus infinity -inf.
static BoundedInt plus_infinity()
Get plus infinity +inf.
signed s32_t
Definition GeneralType.h:47
signed long long s64_t
Definition GeneralType.h:49

◆ isDirectCall()

bool AbstractInterpretation::isDirectCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 610 of file AbstractInterpretation.cpp.

611{
612 const SVFFunction *callfun =callNode->getCalledFunction();
613 if (!callfun)
614 return false;
615 else
616 return funcToWTO.find(callfun->getCallGraphNode()) != funcToWTO.end();
617}
const_iterator end() const
Definition SVFValue.h:451

◆ isExtCall()

bool AbstractInterpretation::isExtCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 566 of file AbstractInterpretation.cpp.

567{
568 return SVFUtil::isExtCall(callNode->getCalledFunction());
569}
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278

◆ isIndirectCall()

bool AbstractInterpretation::isIndirectCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 636 of file AbstractInterpretation.cpp.

637{
639 return callsiteMaps.find(callNode) != callsiteMaps.end();
640}

◆ isRecursiveCall()

bool AbstractInterpretation::isRecursiveCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 582 of file AbstractInterpretation.cpp.

583{
584 const SVFFunction *callfun = callNode->getCalledFunction();
585 if (!callfun)
586 return false;
587 else
588 return recursiveFuns.find(callfun->getCallGraphNode()) != recursiveFuns.end();
589}

◆ isSwitchBranchFeasible()

bool AbstractInterpretation::isSwitchBranchFeasible ( const SVFVar var,
s64_t  succ,
AbstractState as 
)
private

Check if this SwitchInst and succ are satisfiable to the execution state.

Parameters
varvar in switch inst
succthe case value of switch inst
Returns
if this ICFGNode has preceding execution state

Definition at line 404 of file AbstractInterpretation.cpp.

406{
408 IntervalValue& switch_cond = new_es[var->getId()].getInterval();
409 s64_t value = succ;
411 for (SVFStmt *cmpVarInStmt: var->getInEdges())
412 {
414 }
415 switch_cond.meet_with(IntervalValue(value, value));
416 if (switch_cond.isBottom())
417 {
418 return false;
419 }
420 while(!workList.empty())
421 {
422 const SVFStmt* stmt = workList.pop();
423 if (SVFUtil::isa<CopyStmt>(stmt))
424 {
425 IntervalValue& copy_cond = new_es[var->getId()].getInterval();
426 copy_cond.meet_with(IntervalValue(value, value));
427 }
428 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
429 {
430 if (new_es.inVarToAddrsTable(load->getRHSVarID()))
431 {
432 AddressValue &addrs = new_es[load->getRHSVarID()].getAddrs();
433 for (const auto &addr: addrs)
434 {
436 if (new_es.inAddrToValTable(objId))
437 {
438 new_es.load(addr).meet_with(switch_cond);
439 }
440 }
441 }
442 }
443 }
444 as = new_es;
445 return true;
446}
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.

◆ mergeStatesFromPredecessors()

bool AbstractInterpretation::mergeStatesFromPredecessors ( const ICFGNode icfgNode)
private

Check if execution state exist by merging states of predecessor nodes

Parameters
icfgNodeThe icfg node to analyse
Returns
if this node has preceding execution state

get execution state by merging states of predecessor blocks Scenario 1: preblock --—(intraEdge)-—> block, join the preES of inEdges Scenario 2: preblock --—(callEdge)-—> block

Definition at line 133 of file AbstractInterpretation.cpp.

134{
135 std::vector<AbstractState> workList;
137 for (auto& edge: icfgNode->getInEdges())
138 {
139 if (abstractTrace.find(edge->getSrcNode()) != abstractTrace.end())
140 {
141 const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge);
142 if (intraCfgEdge && intraCfgEdge->getCondition())
143 {
144 AbstractState tmpEs = abstractTrace[edge->getSrcNode()];
146 {
147 workList.push_back(tmpEs);
148 }
149 else
150 {
151 // do nothing
152 }
153 }
154 else
155 {
156 workList.push_back(abstractTrace[edge->getSrcNode()]);
157 }
158 }
159 else
160 {
161
162 }
163 }
164 if (workList.size() == 0)
165 {
166 return false;
167 }
168 else
169 {
170 while (!workList.empty())
171 {
172 preAs.joinWith(workList.back());
173 workList.pop_back();
174 }
175 // Has ES on the in edges - Feasible block
176 // update post as
177 abstractTrace[icfgNode] = preAs;
178 return true;
179 }
180}
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.

◆ recursiveCallPass()

void AbstractInterpretation::recursiveCallPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 591 of file AbstractInterpretation.cpp.

592{
595 const RetICFGNode *retNode = callNode->getRetICFGNode();
596 if (retNode->getSVFStmts().size() > 0)
597 {
598 if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
599 {
600 if (!retPE->getLHSVar()->isPointer() &&
601 !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
602 {
603 as[retPE->getLHSVarID()] = IntervalValue::top();
604 }
605 }
606 }
608}
virtual void SkipRecursiveCall(const CallICFGNode *callnode)

◆ runOnModule()

void AbstractInterpretation::runOnModule ( ICFG icfg)
virtual

collect checkpoint

Definition at line 41 of file AbstractInterpretation.cpp.

42{
43 stat->startClk();
44 icfg = _icfg;
47
50
51 analyse();
53 stat->endClk();
55 if (Options::PStat())
57 for (auto& detector: detectors)
58 detector->reportBug();
59}
void performStat() override
Handles external API calls and manages abstract states.
Definition AbsExtAPI.h:46
static const Option< bool > PStat
Definition Options.h:119
virtual void endClk()
Definition SVFStat.h:63
virtual void startClk()
Definition SVFStat.h:58

◆ SkipRecursiveCall()

void AbstractInterpretation::SkipRecursiveCall ( const CallICFGNode callnode)
privatevirtual

Check if this callnode is recursive call and skip it.

Parameters
callnodeCallICFGNode which calls a recursive function

Definition at line 777 of file AbstractInterpretation.cpp.

778{
780 const RetICFGNode *retNode = callNode->getRetICFGNode();
781 if (retNode->getSVFStmts().size() > 0)
782 {
783 if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
784 {
786 if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
787 as[retPE->getLHSVarID()] = IntervalValue::top();
788 }
789 }
790 if (!retNode->getOutEdges().empty())
791 {
792 if (retNode->getOutEdges().size() == 1)
793 {
794
795 }
796 else
797 {
798 return;
799 }
800 }
803 for (const SVFBasicBlock * bb: callNode->getCalledFunction()->getReachableBBs())
804 {
805 for (const ICFGNode* node: bb->getICFGNodeList())
806 {
807 for (const SVFStmt *stmt: node->getSVFStmts())
808 {
809 if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
810 {
811 const SVFVar *rhsVar = store->getRHSVar();
812 u32_t lhs = store->getLHSVarID();
813 if (as.inVarToAddrsTable(lhs))
814 {
815 if (!rhsVar->isPointer() && !rhsVar->isConstDataOrAggDataButNotNullPtr())
816 {
817 const AbstractValue &addrs = as[lhs];
818 for (const auto &addr: addrs.getAddrs())
819 {
820 as.store(addr, IntervalValue::top());
821 }
822 }
823 }
824 }
825 }
826 }
827 }
828}

◆ updateStateOnAddr()

void AbstractInterpretation::updateStateOnAddr ( const AddrStmt addr)
private

Definition at line 1057 of file AbstractInterpretation.cpp.

1058{
1059 AbstractState& as = getAbsStateFromTrace(addr->getICFGNode());
1060 as.initObjVar(SVFUtil::cast<ObjVar>(addr->getRHSVar()));
1061 if (addr->getRHSVar()->getType()->getKind() == SVFType::SVFIntegerTy)
1062 as[addr->getRHSVarID()].getInterval().meet_with(utils->getRangeLimitFromType(addr->getRHSVar()->getType()));
1063 as[addr->getLHSVarID()] = as[addr->getRHSVarID()];
1064}
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.

◆ updateStateOnBinary()

void AbstractInterpretation::updateStateOnBinary ( const BinaryOPStmt binary)
private

Find the comparison predicates in "class BinaryOPStmt:OpCode" under SVF/svf/include/SVFIR/SVFStatements.h You are only required to handle integer predicates, including Add, FAdd, Sub, FSub, Mul, FMul, SDiv, FDiv, UDiv, SRem, FRem, URem, Xor, And, Or, AShr, Shl, LShr

Definition at line 1067 of file AbstractInterpretation.cpp.

1068{
1072 const ICFGNode* node = binary->getICFGNode();
1074 u32_t op0 = binary->getOpVarID(0);
1075 u32_t op1 = binary->getOpVarID(1);
1076 u32_t res = binary->getResID();
1077 if (!as.inVarToValTable(op0)) as[op0] = IntervalValue::top();
1078 if (!as.inVarToValTable(op1)) as[op1] = IntervalValue::top();
1079 IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
1081 switch (binary->getOpcode())
1082 {
1083 case BinaryOPStmt::Add:
1084 case BinaryOPStmt::FAdd:
1085 resVal = (lhs + rhs);
1086 break;
1087 case BinaryOPStmt::Sub:
1088 case BinaryOPStmt::FSub:
1089 resVal = (lhs - rhs);
1090 break;
1091 case BinaryOPStmt::Mul:
1092 case BinaryOPStmt::FMul:
1093 resVal = (lhs * rhs);
1094 break;
1095 case BinaryOPStmt::SDiv:
1096 case BinaryOPStmt::FDiv:
1097 case BinaryOPStmt::UDiv:
1098 resVal = (lhs / rhs);
1099 break;
1100 case BinaryOPStmt::SRem:
1101 case BinaryOPStmt::FRem:
1102 case BinaryOPStmt::URem:
1103 resVal = (lhs % rhs);
1104 break;
1105 case BinaryOPStmt::Xor:
1106 resVal = (lhs ^ rhs);
1107 break;
1108 case BinaryOPStmt::And:
1109 resVal = (lhs & rhs);
1110 break;
1111 case BinaryOPStmt::Or:
1112 resVal = (lhs | rhs);
1113 break;
1114 case BinaryOPStmt::AShr:
1115 resVal = (lhs >> rhs);
1116 break;
1117 case BinaryOPStmt::Shl:
1118 resVal = (lhs << rhs);
1119 break;
1120 case BinaryOPStmt::LShr:
1121 resVal = (lhs >> rhs);
1122 break;
1123 default:
1124 assert(false && "undefined binary: ");
1125 }
1126 as[res] = resVal;
1127}

◆ updateStateOnCall()

void AbstractInterpretation::updateStateOnCall ( const CallPE callPE)
private

Definition at line 1040 of file AbstractInterpretation.cpp.

1041{
1042 AbstractState& as = getAbsStateFromTrace(callPE->getICFGNode());
1043 NodeID lhs = callPE->getLHSVarID();
1044 NodeID rhs = callPE->getRHSVarID();
1045 as[lhs] = as[rhs];
1046}

◆ updateStateOnCmp()

void AbstractInterpretation::updateStateOnCmp ( const CmpStmt cmp)
private

Definition at line 1129 of file AbstractInterpretation.cpp.

1130{
1131 AbstractState& as = getAbsStateFromTrace(cmp->getICFGNode());
1132 u32_t op0 = cmp->getOpVarID(0);
1133 u32_t op1 = cmp->getOpVarID(1);
1134 // if it is address
1135 if (as.inVarToAddrsTable(op0) && as.inVarToAddrsTable(op1))
1136 {
1138 AddressValue addrOp0 = as[op0].getAddrs();
1139 AddressValue addrOp1 = as[op1].getAddrs();
1140 u32_t res = cmp->getResID();
1141 if (addrOp0.equals(addrOp1))
1142 {
1143 resVal = IntervalValue(1, 1);
1144 }
1145 else if (addrOp0.hasIntersect(addrOp1))
1146 {
1147 resVal = IntervalValue(0, 1);
1148 }
1149 else
1150 {
1151 resVal = IntervalValue(0, 0);
1152 }
1153 as[res] = resVal;
1154 }
1155 else
1156 {
1157 if (!as.inVarToValTable(op0))
1159 if (!as.inVarToValTable(op1))
1161 u32_t res = cmp->getResID();
1162 if (as.inVarToValTable(op0) && as.inVarToValTable(op1))
1163 {
1165 if (as[op0].isInterval() && as[op1].isInterval())
1166 {
1167 IntervalValue &lhs = as[op0].getInterval(),
1168 &rhs = as[op1].getInterval();
1169 // AbstractValue
1170 auto predicate = cmp->getPredicate();
1171 switch (predicate)
1172 {
1173 case CmpStmt::ICMP_EQ:
1174 case CmpStmt::FCMP_OEQ:
1175 case CmpStmt::FCMP_UEQ:
1176 resVal = (lhs == rhs);
1177 // resVal = (lhs.getInterval() == rhs.getInterval());
1178 break;
1179 case CmpStmt::ICMP_NE:
1180 case CmpStmt::FCMP_ONE:
1181 case CmpStmt::FCMP_UNE:
1182 resVal = (lhs != rhs);
1183 break;
1184 case CmpStmt::ICMP_UGT:
1185 case CmpStmt::ICMP_SGT:
1186 case CmpStmt::FCMP_OGT:
1187 case CmpStmt::FCMP_UGT:
1188 resVal = (lhs > rhs);
1189 break;
1190 case CmpStmt::ICMP_UGE:
1191 case CmpStmt::ICMP_SGE:
1192 case CmpStmt::FCMP_OGE:
1193 case CmpStmt::FCMP_UGE:
1194 resVal = (lhs >= rhs);
1195 break;
1196 case CmpStmt::ICMP_ULT:
1197 case CmpStmt::ICMP_SLT:
1198 case CmpStmt::FCMP_OLT:
1199 case CmpStmt::FCMP_ULT:
1200 resVal = (lhs < rhs);
1201 break;
1202 case CmpStmt::ICMP_ULE:
1203 case CmpStmt::ICMP_SLE:
1204 case CmpStmt::FCMP_OLE:
1205 case CmpStmt::FCMP_ULE:
1206 resVal = (lhs <= rhs);
1207 break;
1209 resVal = IntervalValue(0, 0);
1210 break;
1211 case CmpStmt::FCMP_TRUE:
1212 resVal = IntervalValue(1, 1);
1213 break;
1214 default:
1215 {
1216 assert(false && "undefined compare: ");
1217 }
1218 }
1219 as[res] = resVal;
1220 }
1221 else if (as[op0].isAddr() && as[op1].isAddr())
1222 {
1223 AddressValue &lhs = as[op0].getAddrs(),
1224 &rhs = as[op1].getAddrs();
1225 auto predicate = cmp->getPredicate();
1226 switch (predicate)
1227 {
1228 case CmpStmt::ICMP_EQ:
1229 case CmpStmt::FCMP_OEQ:
1230 case CmpStmt::FCMP_UEQ:
1231 {
1232 if (lhs.hasIntersect(rhs))
1233 {
1234 resVal = IntervalValue(0, 1);
1235 }
1236 else if (lhs.empty() && rhs.empty())
1237 {
1238 resVal = IntervalValue(1, 1);
1239 }
1240 else
1241 {
1242 resVal = IntervalValue(0, 0);
1243 }
1244 break;
1245 }
1246 case CmpStmt::ICMP_NE:
1247 case CmpStmt::FCMP_ONE:
1248 case CmpStmt::FCMP_UNE:
1249 {
1250 if (lhs.hasIntersect(rhs))
1251 {
1252 resVal = IntervalValue(0, 1);
1253 }
1254 else if (lhs.empty() && rhs.empty())
1255 {
1256 resVal = IntervalValue(0, 0);
1257 }
1258 else
1259 {
1260 resVal = IntervalValue(1, 1);
1261 }
1262 break;
1263 }
1264 case CmpStmt::ICMP_UGT:
1265 case CmpStmt::ICMP_SGT:
1266 case CmpStmt::FCMP_OGT:
1267 case CmpStmt::FCMP_UGT:
1268 {
1269 if (lhs.size() == 1 && rhs.size() == 1)
1270 {
1271 resVal = IntervalValue(*lhs.begin() > *rhs.begin());
1272 }
1273 else
1274 {
1275 resVal = IntervalValue(0, 1);
1276 }
1277 break;
1278 }
1279 case CmpStmt::ICMP_UGE:
1280 case CmpStmt::ICMP_SGE:
1281 case CmpStmt::FCMP_OGE:
1282 case CmpStmt::FCMP_UGE:
1283 {
1284 if (lhs.size() == 1 && rhs.size() == 1)
1285 {
1286 resVal = IntervalValue(*lhs.begin() >= *rhs.begin());
1287 }
1288 else
1289 {
1290 resVal = IntervalValue(0, 1);
1291 }
1292 break;
1293 }
1294 case CmpStmt::ICMP_ULT:
1295 case CmpStmt::ICMP_SLT:
1296 case CmpStmt::FCMP_OLT:
1297 case CmpStmt::FCMP_ULT:
1298 {
1299 if (lhs.size() == 1 && rhs.size() == 1)
1300 {
1301 resVal = IntervalValue(*lhs.begin() < *rhs.begin());
1302 }
1303 else
1304 {
1305 resVal = IntervalValue(0, 1);
1306 }
1307 break;
1308 }
1309 case CmpStmt::ICMP_ULE:
1310 case CmpStmt::ICMP_SLE:
1311 case CmpStmt::FCMP_OLE:
1312 case CmpStmt::FCMP_ULE:
1313 {
1314 if (lhs.size() == 1 && rhs.size() == 1)
1315 {
1316 resVal = IntervalValue(*lhs.begin() <= *rhs.begin());
1317 }
1318 else
1319 {
1320 resVal = IntervalValue(0, 1);
1321 }
1322 break;
1323 }
1325 resVal = IntervalValue(0, 0);
1326 break;
1327 case CmpStmt::FCMP_TRUE:
1328 resVal = IntervalValue(1, 1);
1329 break;
1330 default:
1331 {
1332 assert(false && "undefined compare: ");
1333 }
1334 }
1335 as[res] = resVal;
1336 }
1337 }
1338 }
1339}

◆ updateStateOnCopy()

void AbstractInterpretation::updateStateOnCopy ( const CopyStmt copy)
private

Definition at line 1357 of file AbstractInterpretation.cpp.

1358{
1359 auto getZExtValue = [](AbstractState& as, const SVFVar* var)
1360 {
1361 const SVFType* type = var->getType();
1362 if (SVFUtil::isa<SVFIntegerType>(type))
1363 {
1364 u32_t bits = type->getByteSize() * 8;
1365 if (as[var->getId()].getInterval().is_numeral())
1366 {
1367 if (bits == 8)
1368 {
1369 int8_t signed_i8_value = as[var->getId()].getInterval().getIntNumeral();
1372 }
1373 else if (bits == 16)
1374 {
1375 s16_t signed_i16_value = as[var->getId()].getInterval().getIntNumeral();
1378 }
1379 else if (bits == 32)
1380 {
1381 s32_t signed_i32_value = as[var->getId()].getInterval().getIntNumeral();
1384 }
1385 else if (bits == 64)
1386 {
1387 s64_t signed_i64_value = as[var->getId()].getInterval().getIntNumeral();
1389 // we only support i64 at most
1390 }
1391 else
1392 {
1393 assert(false && "cannot support int type other than u8/16/32/64");
1394 }
1395 }
1396 else
1397 {
1398 return IntervalValue::top(); // TODO: may have better solution
1399 }
1400 }
1401 return IntervalValue::top(); // TODO: may have better solution
1402 };
1403
1404 auto getTruncValue = [&](const AbstractState& as, const SVF::SVFVar* var,
1405 const SVFType* dstType)
1406 {
1407 const IntervalValue& itv = as[var->getId()].getInterval();
1408 if(itv.isBottom()) return itv;
1409 // get the value of ub and lb
1411 s64_t int_ub = itv.ub().getIntNumeral();
1412 // get dst type
1413 u32_t dst_bits = dstType->getByteSize() * 8;
1414 if (dst_bits == 8)
1415 {
1416 // get the signed value of ub and lb
1417 int8_t s8_lb = static_cast<int8_t>(int_lb);
1418 int8_t s8_ub = static_cast<int8_t>(int_ub);
1419 if (s8_lb > s8_ub)
1420 {
1421 // return range of s8
1423 }
1424 return IntervalValue(s8_lb, s8_ub);
1425 }
1426 else if (dst_bits == 16)
1427 {
1428 // get the signed value of ub and lb
1429 s16_t s16_lb = static_cast<s16_t>(int_lb);
1430 s16_t s16_ub = static_cast<s16_t>(int_ub);
1431 if (s16_lb > s16_ub)
1432 {
1433 // return range of s16
1435 }
1436 return IntervalValue(s16_lb, s16_ub);
1437 }
1438 else if (dst_bits == 32)
1439 {
1440 // get the signed value of ub and lb
1441 s32_t s32_lb = static_cast<s32_t>(int_lb);
1442 s32_t s32_ub = static_cast<s32_t>(int_ub);
1443 if (s32_lb > s32_ub)
1444 {
1445 // return range of s32
1447 }
1448 return IntervalValue(s32_lb, s32_ub);
1449 }
1450 else
1451 {
1452 assert(false && "cannot support dst int type other than u8/16/32");
1453 }
1454 };
1455
1456 AbstractState& as = getAbsStateFromTrace(copy->getICFGNode());
1457 u32_t lhs = copy->getLHSVarID();
1458 u32_t rhs = copy->getRHSVarID();
1459
1460 if (copy->getCopyKind() == CopyStmt::COPYVAL)
1461 {
1462 as[lhs] = as[rhs];
1463 }
1464 else if (copy->getCopyKind() == CopyStmt::ZEXT)
1465 {
1466 as[lhs] = getZExtValue(as, copy->getRHSVar());
1467 }
1468 else if (copy->getCopyKind() == CopyStmt::SEXT)
1469 {
1470 as[lhs] = as[rhs].getInterval();
1471 }
1472 else if (copy->getCopyKind() == CopyStmt::FPTOSI)
1473 {
1474 as[lhs] = as[rhs].getInterval();
1475 }
1476 else if (copy->getCopyKind() == CopyStmt::FPTOUI)
1477 {
1478 as[lhs] = as[rhs].getInterval();
1479 }
1480 else if (copy->getCopyKind() == CopyStmt::SITOFP)
1481 {
1482 as[lhs] = as[rhs].getInterval();
1483 }
1484 else if (copy->getCopyKind() == CopyStmt::UITOFP)
1485 {
1486 as[lhs] = as[rhs].getInterval();
1487 }
1488 else if (copy->getCopyKind() == CopyStmt::TRUNC)
1489 {
1490 as[lhs] = getTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
1491 }
1492 else if (copy->getCopyKind() == CopyStmt::FPTRUNC)
1493 {
1494 as[lhs] = as[rhs].getInterval();
1495 }
1496 else if (copy->getCopyKind() == CopyStmt::INTTOPTR)
1497 {
1498 //insert nullptr
1499 }
1500 else if (copy->getCopyKind() == CopyStmt::PTRTOINT)
1501 {
1503 }
1504 else if (copy->getCopyKind() == CopyStmt::BITCAST)
1505 {
1506 if (as[rhs].isAddr())
1507 {
1508 as[lhs] = as[rhs];
1509 }
1510 else
1511 {
1512 // do nothing
1513 }
1514 }
1515 else
1516 {
1517 assert(false && "undefined copy kind");
1518 abort();
1519 }
1520}
newitem type
Definition cJSON.cpp:2739
s64_t getIntNumeral() const
const BoundedInt & lb() const
Return the lower bound.
u32_t getByteSize() const
Definition SVFType.h:244
signed short s16_t
Definition GeneralType.h:53
unsigned short u16_t
Definition GeneralType.h:52

◆ updateStateOnGep()

void AbstractInterpretation::updateStateOnGep ( const GepStmt gep)
private

Definition at line 967 of file AbstractInterpretation.cpp.

968{
969 AbstractState& as = getAbsStateFromTrace(gep->getICFGNode());
970 u32_t rhs = gep->getRHSVarID();
971 u32_t lhs = gep->getLHSVarID();
972 IntervalValue offsetPair = as.getElementIndex(gep);
974 APOffset lb = offsetPair.lb().getIntNumeral() < Options::MaxFieldLimit()?
975 offsetPair.lb().getIntNumeral(): Options::MaxFieldLimit();
976 APOffset ub = offsetPair.ub().getIntNumeral() < Options::MaxFieldLimit()?
977 offsetPair.ub().getIntNumeral(): Options::MaxFieldLimit();
978 for (APOffset i = lb; i <= ub; i++)
979 gepAddrs.join_with(as.getGepObjAddrs(rhs,IntervalValue(i)));
980 as[lhs] = gepAddrs;
981}
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:38
s64_t APOffset
Definition GeneralType.h:60

◆ updateStateOnLoad()

void AbstractInterpretation::updateStateOnLoad ( const LoadStmt load)
private

Definition at line 1341 of file AbstractInterpretation.cpp.

1342{
1344 u32_t rhs = load->getRHSVarID();
1345 u32_t lhs = load->getLHSVarID();
1346 as[lhs] = as.loadValue(rhs);
1347}
NodeID getRHSVarID() const
NodeID getLHSVarID() const
ICFGNode * getICFGNode() const

◆ updateStateOnPhi()

void AbstractInterpretation::updateStateOnPhi ( const PhiStmt phi)
private

Definition at line 1001 of file AbstractInterpretation.cpp.

1002{
1003 const ICFGNode* icfgNode = phi->getICFGNode();
1005 u32_t res = phi->getResID();
1007 for (u32_t i = 0; i < phi->getOpVarNum(); i++)
1008 {
1009 NodeID curId = phi->getOpVarID(i);
1010 const ICFGNode* opICFGNode = phi->getOpICFGNode(i);
1012 {
1016 // if IntraEdge, check the condition, if it is feasible, join the value
1017 // if IntraEdge but not conditional edge, join the value
1018 // if not IntraEdge, join the value
1019 if (edge)
1020 {
1021 const IntraCFGEdge* intraEdge = SVFUtil::cast<IntraCFGEdge>(edge);
1022 if (intraEdge->getCondition())
1023 {
1025 rhs.join_with(opAs[curId]);
1026 }
1027 else
1028 rhs.join_with(opAs[curId]);
1029 }
1030 else
1031 {
1032 rhs.join_with(opAs[curId]);
1033 }
1034 }
1035 }
1036 as[res] = rhs;
1037}
bool hasAbsStateFromTrace(const ICFGNode *node)
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition ICFG.cpp:303

◆ updateStateOnRet()

void AbstractInterpretation::updateStateOnRet ( const RetPE retPE)
private

Definition at line 1048 of file AbstractInterpretation.cpp.

1049{
1051 NodeID lhs = retPE->getLHSVarID();
1052 NodeID rhs = retPE->getRHSVarID();
1053 as[lhs] = as[rhs];
1054}

◆ updateStateOnSelect()

void AbstractInterpretation::updateStateOnSelect ( const SelectStmt select)
private

Definition at line 983 of file AbstractInterpretation.cpp.

984{
985 AbstractState& as = getAbsStateFromTrace(select->getICFGNode());
986 u32_t res = select->getResID();
987 u32_t tval = select->getTrueValue()->getId();
988 u32_t fval = select->getFalseValue()->getId();
989 u32_t cond = select->getCondition()->getId();
990 if (as[cond].getInterval().is_numeral())
991 {
992 as[res] = as[cond].getInterval().is_zero() ? as[fval] : as[tval];
993 }
994 else
995 {
996 as[res] = as[tval];
997 as[res].join_with(as[fval]);
998 }
999}

◆ updateStateOnStore()

void AbstractInterpretation::updateStateOnStore ( const StoreStmt store)
private

Definition at line 1349 of file AbstractInterpretation.cpp.

1350{
1352 u32_t rhs = store->getRHSVarID();
1353 u32_t lhs = store->getLHSVarID();
1354 as.storeValue(lhs, as[rhs]);
1355}

Friends And Related Symbol Documentation

◆ AEAPI

friend class AEAPI
friend

Definition at line 105 of file AbstractInterpretation.h.

◆ AEStat

Definition at line 104 of file AbstractInterpretation.h.

◆ BufOverflowDetector

Definition at line 106 of file AbstractInterpretation.h.

Member Data Documentation

◆ _reverse_predicate

Map<s32_t, s32_t> SVF::AbstractInterpretation::_reverse_predicate
private
Initial value:

Definition at line 308 of file AbstractInterpretation.h.

◆ _switch_lhsrhs_predicate

Map<s32_t, s32_t> SVF::AbstractInterpretation::_switch_lhsrhs_predicate
private
Initial value:

Definition at line 329 of file AbstractInterpretation.h.

◆ abstractTrace

Map<const ICFGNode*, AbstractState> SVF::AbstractInterpretation::abstractTrace
private

Definition at line 295 of file AbstractInterpretation.h.

◆ api

AEAPI* SVF::AbstractInterpretation::api {nullptr}
private

Execution State, used to store the Interval Value of every SVF variable.

Definition at line 248 of file AbstractInterpretation.h.

248{nullptr};

◆ callSiteStack

std::vector<const CallICFGNode*> SVF::AbstractInterpretation::callSiteStack
private

Definition at line 253 of file AbstractInterpretation.h.

◆ checkpoints

Set<const CallICFGNode*> SVF::AbstractInterpretation::checkpoints

Definition at line 132 of file AbstractInterpretation.h.

◆ detectors

std::vector<std::unique_ptr<AEDetector> > SVF::AbstractInterpretation::detectors
private

Definition at line 298 of file AbstractInterpretation.h.

◆ func_map

Map<std::string, std::function<void(const CallICFGNode*)> > SVF::AbstractInterpretation::func_map
private

Definition at line 293 of file AbstractInterpretation.h.

◆ funcToWTO

Map<const CallGraphNode*, ICFGWTO*> SVF::AbstractInterpretation::funcToWTO
private

Definition at line 254 of file AbstractInterpretation.h.

◆ icfg

ICFG* SVF::AbstractInterpretation::icfg
private

Definition at line 250 of file AbstractInterpretation.h.

◆ moduleName

std::string SVF::AbstractInterpretation::moduleName
private

Definition at line 296 of file AbstractInterpretation.h.

◆ recursiveFuns

Set<const CallGraphNode*> SVF::AbstractInterpretation::recursiveFuns
private

Definition at line 255 of file AbstractInterpretation.h.

◆ stat

AEStat* SVF::AbstractInterpretation::stat
private

Definition at line 251 of file AbstractInterpretation.h.

◆ svfir

SVFIR* SVF::AbstractInterpretation::svfir
private

protected data members, also used in subclasses

Definition at line 246 of file AbstractInterpretation.h.

◆ utils

AbsExtAPI* SVF::AbstractInterpretation::utils
private

Definition at line 299 of file AbstractInterpretation.h.


The documentation for this class was generated from the following files: