diff --git a/.codecov.yml b/.codecov.yml index 43f8be91e..660875bf2 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -5,7 +5,7 @@ coverage: status: project: default: - target: 67.85% # If auto, it will compare with the last commit. This could be set to an exact number such as 70% or higher. + target: 67.70% # If auto, it will compare with the last commit. This could be set to an exact number such as 70% or higher. threshold: 0.01% # Allow the coverage to drop by 0.01%, and posting a success status. base: auto patch: diff --git a/svf/include/AE/Core/CFBasicBlockGWTO.h b/svf/include/AE/Core/CFBasicBlockGWTO.h deleted file mode 100644 index 4f864a4c6..000000000 --- a/svf/include/AE/Core/CFBasicBlockGWTO.h +++ /dev/null @@ -1,85 +0,0 @@ -//===- CFBasicBlockGWTO.h -- WTO for CFBasicBlockGraph----------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -//===----------------------------------------------------------------------===// - -/* - * CFBasicBlockGWTO.h - * - * The implementation is based on F. Bourdoncle's paper: - * "Efficient chaotic iteration strategies with widenings", Formal - * Methods in Programming and Their Applications, 1993, pages 128-141. - * - * Created on: Jan 22, 2024 - * Author: Xiao Cheng - * - */ -#ifndef SVF_CFBASICBLOCKGWTO_H -#define SVF_CFBASICBLOCKGWTO_H -#include "Graphs/CFBasicBlockG.h" -#include "Graphs/WTO.h" - -namespace SVF -{ -typedef WTOComponent CFBasicBlockGWTOComp; -typedef WTONode CFBasicBlockGWTONode; -typedef WTOCycle CFBasicBlockGWTOCycle; - -class CFBasicBlockGWTO : public WTO -{ -public: - typedef WTO Base; - typedef WTOComponentVisitor::WTONodeT - CFBasicBlockGWTONode; - - explicit CFBasicBlockGWTO(CFBasicBlockGraph* graph, - const CFBasicBlockNode* node) - : Base(graph, node) - { - } - - virtual ~CFBasicBlockGWTO() = default; - - inline void forEachSuccessor( - const CFBasicBlockNode* node, - std::function func) const override - { - if (const auto* callNode = - SVFUtil::dyn_cast(node->getICFGNodes().front())) - { - const CFBasicBlockNode* succ = _graph->getCFBasicBlockNode( - callNode->getRetICFGNode()->getId()); - func(succ); - } - else - { - for (const auto& e : node->getOutEdges()) - { - if (e->getICFGEdge() && - (!e->getICFGEdge()->isIntraCFGEdge() || - node->getFunction() != e->getDstNode()->getFunction())) - continue; - func(e->getDstNode()); - } - } - } -}; -} // namespace SVF -#endif // SVF_CFBASICBLOCKGWTO_H diff --git a/svf/include/AE/Core/ICFGWTO.h b/svf/include/AE/Core/ICFGWTO.h index 34f6e4875..0aba1c8c8 100644 --- a/svf/include/AE/Core/ICFGWTO.h +++ b/svf/include/AE/Core/ICFGWTO.h @@ -52,6 +52,10 @@ class ICFGWTO : public WTO explicit ICFGWTO(ICFG* graph, const ICFGNode* node) : Base(graph, node) {} + virtual ~ICFGWTO() + { + } + inline void forEachSuccessor( const ICFGNode* node, std::function func) const override diff --git a/svf/include/AE/Core/IntervalExeState.h b/svf/include/AE/Core/IntervalExeState.h index 6b1be7244..affc0489b 100644 --- a/svf/include/AE/Core/IntervalExeState.h +++ b/svf/include/AE/Core/IntervalExeState.h @@ -433,6 +433,8 @@ class IntervalExeState : public IntervalESBase return *this; } + virtual void printExprValues(std::ostream &oss) const override; + /// move constructor IntervalExeState(IntervalExeState &&rhs) : IntervalESBase(std::move(rhs)) { diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index fb76ca8f9..37db43ecf 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -32,7 +32,7 @@ #include "AE/Svfexe/SVFIR2ItvExeState.h" #include "Util/WorkList.h" #include "MSSA/SVFGBuilder.h" -#include "AE/Core/CFBasicBlockGWTO.h" +#include "AE/Core/ICFGWTO.h" #include "WPA/Andersen.h" #include "Util/SVFBugReport.h" @@ -46,7 +46,7 @@ class AEAPI; enum class AEKind { AbstractExecution, - BufOverflowChecker + BufOverflowChecker, }; /// AEStat: Statistic for AE @@ -120,7 +120,6 @@ class AbstractExecution virtual void runOnModule(SVFIR* svfModule); - /// Destructor virtual ~AbstractExecution(); @@ -145,37 +144,37 @@ class AbstractExecution void markRecursiveFuns(); /** - * Check if execution state exist by merging states of predecessor blocks + * Check if execution state exist by merging states of predecessor nodes * - * @param block The basic block to analyse - * @return if this block has preceding execution state + * @param node The ICFGNode to analyse + * @return if this node has preceding execution state */ - bool hasInEdgesES(const CFBasicBlockNode *block); + bool hasInEdgesES(const ICFGNode *node); /** * Check if execution state exist at the branch edge * - * @param intraEdge the edge from CmpStmt to the next Block + * @param intraEdge the edge from CmpStmt to the next node * @return if this edge is feasible */ bool hasBranchES(const IntraCFGEdge* intraEdge, IntervalExeState& es); /** - * handle instructions in svf basic blocks + * handle instructions in ICFGNode * * @param block basic block that has a series of instructions */ - void handleBlock(const CFBasicBlockNode *block); + void handleWTONode(const ICFGNode* node); /** - * handle one instruction in svf basic blocks + * handle one instruction in ICFGNode * * @param node ICFGNode which has a single instruction */ virtual void handleICFGNode(const ICFGNode *node); /** - * handle call node in svf basic blocks + * handle call node in ICFGNode * * @param node ICFGNode which has a single CallICFGNode */ @@ -186,7 +185,7 @@ class AbstractExecution * * @param cycle WTOCycle which has weak topo order of basic blocks and nested cycles */ - virtual void handleCycle(const CFBasicBlockGWTOCycle *cycle); + virtual void handleCycle(const ICFGWTOCycle *cycle); /** * handle user defined function, ext function is not included. @@ -221,7 +220,7 @@ class AbstractExecution * * @param cmpStmt CmpStmt is a conditional branch statement * @param succ the value of cmpStmt (True or False) - * @return if this block has preceding execution state + * @return if this ICFGNode has preceding execution state */ bool hasCmpBranchES(const CmpStmt* cmpStmt, s64_t succ, IntervalExeState& es); @@ -230,7 +229,7 @@ class AbstractExecution * * @param var var in switch inst * @param succ the case value of switch inst - * @return if this block has preceding execution state + * @return if this ICFGNode has preceding execution state */ bool hasSwitchBranchES(const SVFVar* var, s64_t succ, IntervalExeState& es); @@ -249,33 +248,32 @@ class AbstractExecution SVFBugReport _recoder; std::vector _callSiteStack; Map _nodeToBugInfo; + AndersenWaveDiff *_ander; + Map _funcToWTO; + Set _recursiveFuns; private: // helper functions in handleCallSite - bool isExtCall(const CallICFGNode* callNode); - void extCallPass(const CallICFGNode* callNode); - bool isRecursiveCall(const CallICFGNode* callNode); - void recursiveCallPass(const CallICFGNode* callNode); - bool isDirectCall(const CallICFGNode* callNode); - void directCallFunPass(const CallICFGNode* callNode); - bool isIndirectCall(const CallICFGNode* callNode); - void indirectCallFunPass(const CallICFGNode* callNode); + 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); // helper functions in hasInEdgesES - bool isFunEntry(const CFBasicBlockNode* block); - bool isGlobalEntry(const CFBasicBlockNode* block); + bool isFunEntry(const ICFGNode* node); + bool isGlobalEntry(const ICFGNode* node); // helper functions in handleCycle - bool widenFixpointPass(const CFBasicBlockNode* cycle_head, IntervalExeState& pre_es); - bool narrowFixpointPass(const CFBasicBlockNode* cycle_head, IntervalExeState& pre_es); + bool widenFixpointPass(const ICFGNode* cycle_head, IntervalExeState& pre_es); + bool narrowFixpointPass(const ICFGNode* cycle_head, IntervalExeState& pre_es); // private data - CFBasicBlockGraph* _CFBlockG; - AndersenWaveDiff *_ander; - Map _preES; - Map _postES; - Map _funcToWTO; - Set _recursiveFuns; + Map _preES; + Map _postES; std::string _moduleName; }; diff --git a/svf/include/Graphs/CFBasicBlockG.h b/svf/include/Graphs/CFBasicBlockG.h deleted file mode 100644 index 3f9be8ca5..000000000 --- a/svf/include/Graphs/CFBasicBlockG.h +++ /dev/null @@ -1,581 +0,0 @@ -//===- CFBasicBlockG.h ----------------------------------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero 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 Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -// -//===----------------------------------------------------------------------===// - -/* - * CFBasicBlockG.h - * - * Created on: 24 Dec. 2022 - * Author: Xiao, Jiawei - */ - -#ifndef SVF_CFBASICBLOCKG_H -#define SVF_CFBASICBLOCKG_H -#include "Util/SVFUtil.h" -#include "Graphs/ICFG.h" -#include "Graphs/GenericGraph.h" - -namespace SVF -{ -class CFBasicBlockNode; -class SVFIR; - -typedef GenericEdge GenericCFBasicBlockEdgeTy; - -class CFBasicBlockEdge : public GenericCFBasicBlockEdgeTy -{ -public: - typedef struct equalCFBBEdge - { - bool - operator()(const CFBasicBlockEdge *lhs, const CFBasicBlockEdge *rhs) const - { - if (lhs->getSrcID() != rhs->getSrcID()) - return lhs->getSrcID() < rhs->getSrcID(); - else if (lhs->getDstID() != rhs->getDstID()) - return lhs->getDstID() < rhs->getDstID(); - else - return lhs->getICFGEdge() < rhs->getICFGEdge(); - } - } equalICFGEdgeWrapper; - - typedef OrderedSet CFBBEdgeSetTy; - typedef CFBBEdgeSetTy::iterator iterator; - typedef CFBBEdgeSetTy::const_iterator const_iterator; - -private: - const ICFGEdge *_icfgEdge; - -public: - CFBasicBlockEdge(CFBasicBlockNode* src, CFBasicBlockNode* dst, - const ICFGEdge* edge) - : GenericCFBasicBlockEdgeTy(src, dst, 0), _icfgEdge(edge) - { - } - - CFBasicBlockEdge(CFBasicBlockNode* src, CFBasicBlockNode* dst) - : GenericCFBasicBlockEdgeTy(src, dst, 0), _icfgEdge(nullptr) - { - } - - friend std::ostream &operator<<(std::ostream &o, const CFBasicBlockEdge &edge) - { - o << edge.toString(); - return o; - } - - virtual const std::string toString() const - { - std::string str; - std::stringstream rawstr(str); - rawstr << "CFBBGEdge: [CFBBGNode" << getDstID() << " <-- CFBBGNode" << getSrcID() << "]\t"; - return rawstr.str(); - } - - inline const ICFGEdge *getICFGEdge() const - { - return _icfgEdge; - } - - using SVF::GenericEdge::operator==; - /// Add the hash function for std::set (we also can overload operator< to implement this) - // and duplicated elements in the set are not inserted (binary tree comparison) - //@{ - - virtual inline bool operator==(const CFBasicBlockEdge *rhs) const - { - return (rhs->getSrcID() == this->getSrcID() && rhs->getDstID() == this->getDstID() && - rhs->getICFGEdge() == this->getICFGEdge()); - } - //@} - -}; - -typedef GenericNode GenericCFBasicBlockNodeTy; - -class CFBasicBlockNode : public GenericCFBasicBlockNodeTy -{ -public: - typedef CFBasicBlockEdge::CFBBEdgeSetTy CFBBEdgeSetTy; - typedef CFBasicBlockEdge::CFBBEdgeSetTy ::iterator iterator; - typedef CFBasicBlockEdge::CFBBEdgeSetTy::const_iterator const_iterator; - -private: - std::vector _icfgNodes; /// Every CBFGNode holds a vector of ICFGNodes - CFBBEdgeSetTy InEdges; ///< all incoming edge of this node - CFBBEdgeSetTy OutEdges; ///< all outgoing edge of this node - -public: - CFBasicBlockNode(std::vector icfgNodes) - : GenericCFBasicBlockNodeTy((*icfgNodes.begin())->getId(), 0), - _icfgNodes(SVFUtil::move(icfgNodes)) - { - } - - virtual ~CFBasicBlockNode() - { - for (auto edge : OutEdges) - delete edge; - } - - friend std::ostream &operator<<(std::ostream &o, const CFBasicBlockNode &node) - { - o << node.toString(); - return o; - } - - virtual const std::string toString() const; - - inline std::string getName() const - { - assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); - return (*_icfgNodes.begin())->getBB()->getName(); - } - - inline const std::vector& getICFGNodes() const - { - return _icfgNodes; - } - - inline const SVFFunction *getFunction() const - { - assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); - return (*_icfgNodes.begin())->getFun(); - } - - inline std::vector::const_iterator begin() const - { - return _icfgNodes.cbegin(); - } - - inline std::vector::const_iterator end() const - { - return _icfgNodes.cend(); - } - - inline void removeNode(const ICFGNode* node) - { - const auto it = std::find(_icfgNodes.begin(), _icfgNodes.end(), node); - assert(it != _icfgNodes.end() && "icfg node not in BB?"); - _icfgNodes.erase(it); - } - - inline void addNode(const ICFGNode* node) - { - _icfgNodes.push_back(node); - } - - inline u32_t getICFGNodeNum() const - { - return _icfgNodes.size(); - } - -public: - /// Get incoming/outgoing edge set - ///@{ - inline const CFBBEdgeSetTy &getOutEdges() const - { - return OutEdges; - } - - inline const CFBBEdgeSetTy &getInEdges() const - { - return InEdges; - } - ///@} - - /// Has incoming/outgoing edge set - //@{ - inline bool hasIncomingEdge() const - { - return (InEdges.empty() == false); - } - - inline bool hasOutgoingEdge() const - { - return (OutEdges.empty() == false); - } - //@} - - /// iterators - //@{ - inline iterator OutEdgeBegin() - { - return OutEdges.begin(); - } - - inline iterator OutEdgeEnd() - { - return OutEdges.end(); - } - - inline iterator InEdgeBegin() - { - return InEdges.begin(); - } - - inline iterator InEdgeEnd() - { - return InEdges.end(); - } - - inline const_iterator OutEdgeBegin() const - { - return OutEdges.begin(); - } - - inline const_iterator OutEdgeEnd() const - { - return OutEdges.end(); - } - - inline const_iterator InEdgeBegin() const - { - return InEdges.begin(); - } - - inline const_iterator InEdgeEnd() const - { - return InEdges.end(); - } - //@} - - /// Add incoming and outgoing edges - //@{ - inline bool addIncomingEdge(CFBasicBlockEdge *inEdge) - { - return InEdges.insert(inEdge).second; - } - - inline bool addOutgoingEdge(CFBasicBlockEdge *outEdge) - { - return OutEdges.insert(outEdge).second; - } - //@} - - /// Remove incoming and outgoing edges - ///@{ - inline u32_t removeIncomingEdge(CFBasicBlockEdge *edge) - { - assert(InEdges.find(edge) != InEdges.end() && "can not find in edge in SVFG node"); - return InEdges.erase(edge); - } - - inline u32_t removeOutgoingEdge(CFBasicBlockEdge *edge) - { - assert(OutEdges.find(edge) != OutEdges.end() && "can not find out edge in SVFG node"); - return OutEdges.erase(edge); - } - ///@} - - /// Find incoming and outgoing edges - //@{ - inline CFBasicBlockEdge *hasIncomingEdge(CFBasicBlockEdge *edge) const - { - const_iterator it = InEdges.find(edge); - if (it != InEdges.end()) - return *it; - else - return nullptr; - } - - inline CFBasicBlockEdge *hasOutgoingEdge(CFBasicBlockEdge *edge) const - { - const_iterator it = OutEdges.find(edge); - if (it != OutEdges.end()) - return *it; - else - return nullptr; - } - //@} -}; - -typedef GenericGraph GenericCFBasicBlockGTy; - -class CFBasicBlockGraph : public GenericCFBasicBlockGTy -{ - friend class CFBasicBlockGBuilder; -private: - u32_t _totalCFBasicBlockNode{0}; - u32_t _totalCFBasicBlockEdge{0}; -public: - - CFBasicBlockGraph() = default; - - ~CFBasicBlockGraph() override = default; - - /// Dump graph into dot file - void dump(const std::string &filename) - { - GraphPrinter::WriteGraphToFile(SVFUtil::outs(), filename, this); - } - - inline CFBasicBlockNode *getCFBasicBlockNode(u32_t id) const - { - if (!hasGNode(id)) return nullptr; - return getGNode(id); - } - - inline bool hasCFBasicBlockNode(NodeID id) const - { - return hasGNode(id); - } - - - bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst, ICFGEdge *icfgEdge) - { - CFBasicBlockEdge edge(src, dst, icfgEdge); - CFBasicBlockEdge *outEdge = src->hasOutgoingEdge(&edge); - CFBasicBlockEdge *inEdge = dst->hasIncomingEdge(&edge); - if (outEdge && inEdge) - { - assert(outEdge == inEdge && "edges not match"); - return true; - } - else - return false; - } - - inline bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst) const - { - for (const auto &e: src->getOutEdges()) - { - if (e->getDstNode() == dst) - return true; - } - return false; - } - - CFBasicBlockEdge* getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst, const ICFGEdge *icfgEdge); - - std::vector getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst); - - /// Remove a ICFGEdgeWrapper - inline void removeCFBBEdge(CFBasicBlockEdge *edge) - { - if (edge->getDstNode()->hasIncomingEdge(edge)) - { - edge->getDstNode()->removeIncomingEdge(edge); - } - if (edge->getSrcNode()->hasOutgoingEdge(edge)) - { - edge->getSrcNode()->removeOutgoingEdge(edge); - } - delete edge; - _totalCFBasicBlockEdge--; - } - - /// Remove a ICFGNodeWrapper - inline void removeCFBBNode(CFBasicBlockNode *node) - { - std::set temp; - for (CFBasicBlockEdge *e: node->getInEdges()) - temp.insert(e); - for (CFBasicBlockEdge *e: node->getOutEdges()) - temp.insert(e); - for (CFBasicBlockEdge *e: temp) - { - removeCFBBEdge(e); - } - removeGNode(node); - _totalCFBasicBlockNode--; - } - - - /// Remove node from nodeID - inline bool removeCFBBNode(NodeID id) - { - if (hasGNode(id)) - { - removeCFBBNode(getGNode(id)); - return true; - } - return false; - } - - /// Add ICFGEdgeWrapper - inline bool addCFBBEdge(CFBasicBlockEdge *edge) - { - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - assert(added1 && added2 && "edge not added??"); - _totalCFBasicBlockEdge++; - return added1 && added2; - } - - /// Add a ICFGNodeWrapper - virtual inline void addCFBBNode(CFBasicBlockNode *node) - { - addGNode(node->getId(), node); - _totalCFBasicBlockNode++; - } -}; - -} - - -namespace SVF -{ -/* ! - * GenericGraphTraits specializations for generic graph algorithms. - * Provide graph traits for traversing from a constraint node using standard graph ICFGTraversals. - */ -template<> -struct GenericGraphTraits - : public GenericGraphTraits *> -{ -}; - -/// Inverse GenericGraphTraits specializations for call graph node, it is used for inverse ICFGTraversal. -template<> -struct GenericGraphTraits > : public GenericGraphTraits< - Inverse *> > -{ -}; - -template<> -struct GenericGraphTraits - : public GenericGraphTraits *> -{ - typedef SVF::CFBasicBlockNode *NodeRef; -}; - -} // End namespace SVF - -namespace SVF -{ -template<> -struct DOTGraphTraits : public DOTGraphTraits -{ - - typedef SVF::CFBasicBlockNode NodeType; - - DOTGraphTraits(bool isSimple = false) : - DOTGraphTraits(isSimple) - { - } - - /// Return name of the graph - static std::string getGraphName(SVF::CFBasicBlockGraph *) - { - return "CFBasicBlockGraph"; - } - - std::string getNodeLabel(NodeType *node, SVF::CFBasicBlockGraph *graph) - { - return getSimpleNodeLabel(node, graph); - } - - /// Return the label of an ICFG node - static std::string getSimpleNodeLabel(NodeType *node, SVF::CFBasicBlockGraph *) - { - std::string str; - std::stringstream rawstr(str); - rawstr << "NodeID: " << node->getId() << "\n"; - rawstr << node->toString(); - - return rawstr.str(); - } - - static std::string getNodeAttributes(NodeType *node, SVF::CFBasicBlockGraph *) - { - std::string str; - std::stringstream rawstr(str); - if(node->getICFGNodes().size() == 1) - { - const ICFGNode* n = node->getICFGNodes()[0]; - if(SVFUtil::isa(n)) - { - rawstr << "color=black"; - } - else if(SVFUtil::isa(n)) - { - rawstr << "color=yellow"; - } - else if(SVFUtil::isa(n)) - { - rawstr << "color=green"; - } - else if(SVFUtil::isa(n)) - { - rawstr << "color=red"; - } - else if(SVFUtil::isa(n)) - { - rawstr << "color=blue"; - } - else if(SVFUtil::isa(n)) - { - rawstr << "color=purple"; - } - else - assert(false && "no such kind of node!!"); - } - else - { - rawstr << "color=black"; - } - rawstr << ""; - return rawstr.str(); - } - - template - static std::string getEdgeAttributes(NodeType *, EdgeIter EI, SVF::CFBasicBlockGraph *) - { - CFBasicBlockEdge* edge = *(EI.getCurrent()); - assert(edge && "No edge found!!"); - if (edge->getICFGEdge()) - { - if (SVFUtil::isa(edge->getICFGEdge())) - { - return "style=solid,color=red"; - } - else if (SVFUtil::isa(edge->getICFGEdge())) - return "style=solid,color=blue"; - else - return "style=solid"; - } - else - { - return "style=solid"; - } - } - - template - static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI) - { - CFBasicBlockEdge* edge = *(EI.getCurrent()); - assert(edge && "No edge found!!"); - - std::string str; - std::stringstream rawstr(str); - if (edge->getICFGEdge()) - { - if (const CallCFGEdge* dirCall = SVFUtil::dyn_cast(edge->getICFGEdge())) - rawstr << dirCall->getCallSite(); - else if (const RetCFGEdge* dirRet = SVFUtil::dyn_cast(edge->getICFGEdge())) - rawstr << dirRet->getCallSite(); - } - return rawstr.str(); - } -}; -} -#endif //SVF_CFBASICBLOCKG_H \ No newline at end of file diff --git a/svf/include/Graphs/IRGraph.h b/svf/include/Graphs/IRGraph.h index f295352b2..19c1fa688 100644 --- a/svf/include/Graphs/IRGraph.h +++ b/svf/include/Graphs/IRGraph.h @@ -36,7 +36,6 @@ #include "Util/NodeIDAllocator.h" #include "Util/SVFUtil.h" #include "Graphs/ICFG.h" -#include "Graphs/CFBasicBlockG.h" namespace SVF { diff --git a/svf/include/Util/CFBasicBlockGBuilder.h b/svf/include/Util/CFBasicBlockGBuilder.h deleted file mode 100644 index fc686e16e..000000000 --- a/svf/include/Util/CFBasicBlockGBuilder.h +++ /dev/null @@ -1,64 +0,0 @@ -//===- CFBasicBlockGBuilder.h ----------------------------------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero 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 Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -// -//===----------------------------------------------------------------------===// - -/* - * CFBasicBlockGBuilder.h - * - * Created on: 17 Oct. 2023 - * Author: Xiao, Jiawei - */ - -#include "Graphs/CFBasicBlockG.h" - -namespace SVF -{ - -class CFBasicBlockGBuilder -{ - -private: - CFBasicBlockGraph* _CFBasicBlockG; - -public: - CFBasicBlockGBuilder() : _CFBasicBlockG() {} - - ~CFBasicBlockGBuilder() - { - delete _CFBasicBlockG; - } - - virtual void build(ICFG* icfg); - - inline CFBasicBlockGraph* getCFBasicBlockGraph() - { - return _CFBasicBlockG; - } -private: - void initCFBasicBlockGNodes(ICFG *icfg, Map> &bbToNodes); - - void addInterBBEdge(ICFG *icfg, Map> &bbToNodes); - - void addIntraBBEdge(ICFG *icfg, Map> &bbToNodes); - - void addInterProceduralEdge(ICFG *icfg, Map> &bbToNodes); -}; -} \ No newline at end of file diff --git a/svf/lib/AE/Core/IntervalExeState.cpp b/svf/lib/AE/Core/IntervalExeState.cpp index eb86eb54c..e4fb5d80f 100644 --- a/svf/lib/AE/Core/IntervalExeState.cpp +++ b/svf/lib/AE/Core/IntervalExeState.cpp @@ -310,3 +310,20 @@ void IntervalExeState::meetWith(const IntervalExeState& other) { IntervalESBase::meetWith(other); } + + +/// Print values of all expressions +void IntervalExeState::printExprValues(std::ostream &oss) const +{ + oss << "-----------Var and Value-----------\n"; + printTable(_varToItvVal, oss); + printTable(_locToItvVal, oss); + printTable(_varToAddrs, oss); + printTable(_locToAddrs, oss); + oss << "------------Global---------------------\n"; + printTable(globalES._varToItvVal, oss); + printTable(globalES._locToItvVal, oss); + printTable(globalES._varToAddrs, oss); + printTable(globalES._locToAddrs, oss); + +} diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 5599e31e3..5dacb28c8 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -25,7 +25,6 @@ // Created by Jiawei Wang on 2024/1/10. // #include "WPA/Andersen.h" -#include "Util/CFBasicBlockGBuilder.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" #include "Util/Options.h" @@ -103,11 +102,8 @@ void AbstractExecution::runOnModule(SVF::SVFIR *svfModule) // init SSE External API Handler _callgraph = _ander->getPTACallGraph(); _icfg = _svfir->getICFG(); - CFBasicBlockGBuilder CFBGBuilder; _icfg->updateCallGraph(_callgraph); - CFBGBuilder.build(_icfg); - _CFBlockG = CFBGBuilder.getCFBasicBlockGraph(); /// collect checkpoint _api->collectCheckPoint(); @@ -115,13 +111,9 @@ void AbstractExecution::runOnModule(SVF::SVFIR *svfModule) markRecursiveFuns(); for (const SVFFunction* fun: _svfir->getModule()->getFunctionSet()) { - if (_CFBlockG->hasGNode(_icfg->getFunEntryICFGNode(fun)->getId()) ) - { - const CFBasicBlockNode *node = _CFBlockG->getGNode(_icfg->getFunEntryICFGNode(fun)->getId()); - auto *wto = new CFBasicBlockGWTO(_CFBlockG, node); - wto->init(); - _funcToWTO[fun] = wto; - } + auto *wto = new ICFGWTO(_icfg, _icfg->getFunEntryICFGNode(fun)); + wto->init(); + _funcToWTO[fun] = wto; } analyse(); _api->checkPointAllSet(); @@ -213,7 +205,7 @@ void AbstractExecution::handleGlobalNode() /// get execution state by merging states of predecessor blocks /// Scenario 1: preblock -----(intraEdge)----> block, join the preES of inEdges /// Scenario 2: preblock -----(callEdge)----> block -bool AbstractExecution::hasInEdgesES(const CFBasicBlockNode *block) +bool AbstractExecution::hasInEdgesES(const ICFGNode *block) { if (isGlobalEntry(block)) { @@ -229,7 +221,7 @@ bool AbstractExecution::hasInEdgesES(const CFBasicBlockNode *block) { if (_postES.find(edge->getSrcNode()) != _postES.end()) { - const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast(edge->getICFGEdge()); + const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast(edge); if (intraCfgEdge && intraCfgEdge->getCondition()) { IntervalExeState tmpEs = _postES[edge->getSrcNode()]; @@ -267,9 +259,9 @@ bool AbstractExecution::hasInEdgesES(const CFBasicBlockNode *block) assert(false && "implement this part"); } -bool AbstractExecution::isFunEntry(const SVF::CFBasicBlockNode *block) +bool AbstractExecution::isFunEntry(const SVF::ICFGNode *block) { - if (SVFUtil::isa(*block->getICFGNodes().begin())) + if (SVFUtil::isa(block)) { if (_preES.find(block) != _preES.end()) { @@ -279,12 +271,15 @@ bool AbstractExecution::isFunEntry(const SVF::CFBasicBlockNode *block) return false; } -bool AbstractExecution::isGlobalEntry(const SVF::CFBasicBlockNode *block) +bool AbstractExecution::isGlobalEntry(const SVF::ICFGNode *block) { - if (!block->hasIncomingEdge()) - return true; - else - return false; + for (auto *edge : _icfg->getGlobalICFGNode()->getOutEdges()) { + if (edge->getDstNode() == block) + { + return true; + } + } + return false; } bool AbstractExecution::hasCmpBranchES(const CmpStmt* cmpStmt, s64_t succ, IntervalExeState& es) @@ -587,11 +582,11 @@ bool AbstractExecution::hasBranchES(const IntraCFGEdge* intraEdge, IntervalExeSt return true; } /// handle instructions in svf basic blocks -void AbstractExecution::handleBlock(const CFBasicBlockNode *block) +void AbstractExecution::handleWTONode(const ICFGNode *node) { _stat->getBlockTrace()++; // Get execution states from in edges - if (!hasInEdgesES(block)) + if (!hasInEdgesES(node)) { // No ES on the in edges - Infeasible block return; @@ -600,22 +595,13 @@ void AbstractExecution::handleBlock(const CFBasicBlockNode *block) { // Has ES on the in edges - Feasible block // Get execution state from in edges - _svfir2ExeState->setEs(_preES[block]); + _svfir2ExeState->setEs(_preES[node]); } std::deque worklist; - for (auto it = block->begin(); it != block->end(); ++it) - { - worklist.push_back(*it); - } - while(!worklist.empty()) - { - const ICFGNode* curICFGNode = worklist.front(); - worklist.pop_front(); - handleICFGNode(curICFGNode); - } - _preES.erase(block); - _postES[block] = _svfir2ExeState->getEs(); + handleICFGNode(node); + _preES.erase(node); + _postES[node] = _svfir2ExeState->getEs(); } void AbstractExecution::handleCallSite(const ICFGNode* node) @@ -677,12 +663,13 @@ void AbstractExecution::recursiveCallPass(const SVF::CallICFGNode *callNode) if (const RetPE *retPE = SVFUtil::dyn_cast(*retNode->getSVFStmts().begin())) { if (!retPE->getLHSVar()->isPointer() && - !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr()) + !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr()) { _svfir2ExeState->getEs()[retPE->getLHSVarID()] = IntervalValue::top(); } } } + _postES[retNode] = _svfir2ExeState->getEs(); } bool AbstractExecution::isDirectCall(const SVF::CallICFGNode *callNode) @@ -696,15 +683,14 @@ void AbstractExecution::directCallFunPass(const SVF::CallICFGNode *callNode) IntervalExeState preES = _svfir2ExeState->getEs(); _callSiteStack.push_back(callNode); - auto* curBlockNode = _CFBlockG->getCFBasicBlockNode(callNode->getId()); - _postES[curBlockNode] = _svfir2ExeState->getEs(); + _postES[callNode] = _svfir2ExeState->getEs(); handleFunc(callfun); _callSiteStack.pop_back(); // handle Ret node const RetICFGNode *retNode = callNode->getRetICFGNode(); // resume ES to callnode - _postES[_CFBlockG->getCFBasicBlockNode(retNode->getId())] = _postES[_CFBlockG->getCFBasicBlockNode(callNode->getId())]; + _postES[retNode] = _postES[callNode]; } bool AbstractExecution::isIndirectCall(const SVF::CallICFGNode *callNode) @@ -729,15 +715,14 @@ void AbstractExecution::indirectCallFunPass(const SVF::CallICFGNode *callNode) { IntervalExeState preES = _svfir2ExeState->getEs(); _callSiteStack.push_back(callNode); - auto *curBlockNode = _CFBlockG->getCFBasicBlockNode(callNode->getId()); - _postES[curBlockNode] = _svfir2ExeState->getEs(); + _postES[callNode] = _svfir2ExeState->getEs(); handleFunc(callfun); _callSiteStack.pop_back(); // handle Ret node const RetICFGNode *retNode = callNode->getRetICFGNode(); - _postES[_CFBlockG->getCFBasicBlockNode(retNode->getId())] = _postES[_CFBlockG->getCFBasicBlockNode(callNode->getId())]; + _postES[retNode] = _postES[callNode]; } } @@ -764,7 +749,7 @@ void AbstractExecution::handleICFGNode(const ICFGNode *curICFGNode) } /// handle wto cycle (loop) -void AbstractExecution::handleCycle(const CFBasicBlockGWTOCycle *cycle) +void AbstractExecution::handleCycle(const ICFGWTOCycle *cycle) { // Get execution states from in edges if (!hasInEdgesES(cycle->head())) @@ -778,9 +763,9 @@ void AbstractExecution::handleCycle(const CFBasicBlockGWTOCycle *cycle) bool incresing = true; for (int i = 0; ; i++) { - const CFBasicBlockNode* cycle_head = cycle->head(); + const ICFGNode* cycle_head = cycle->head(); // handle cycle head - handleBlock(cycle_head); + handleWTONode(cycle_head); if (i < widen_delay) { if (i> 0 && pre_es >= _postES[cycle_head]) @@ -797,9 +782,12 @@ void AbstractExecution::handleCycle(const CFBasicBlockGWTOCycle *cycle) { bool is_fixpoint = widenFixpointPass(cycle_head, pre_es); if (is_fixpoint) + { incresing = false; + continue; + } } - if (!incresing) + else if (!incresing) { bool is_fixpoint = narrowFixpointPass(cycle_head, pre_es); if (is_fixpoint) @@ -809,14 +797,14 @@ void AbstractExecution::handleCycle(const CFBasicBlockGWTOCycle *cycle) } for (auto it = cycle->begin(); it != cycle->end(); ++it) { - const CFBasicBlockGWTOComp* cur = *it; - if (const CFBasicBlockGWTONode* vertex = SVFUtil::dyn_cast(cur)) + const ICFGWTOComp* cur = *it; + if (const ICFGWTONode* vertex = SVFUtil::dyn_cast(cur)) { - handleBlock(vertex->node()); + handleWTONode(vertex->node()); } - else if (const CFBasicBlockGWTOCycle* cycle = SVFUtil::dyn_cast(cur)) + else if (const ICFGWTOCycle* cycle2 = SVFUtil::dyn_cast(cur)) { - handleCycle(cycle); + handleCycle(cycle2); } else { @@ -826,7 +814,7 @@ void AbstractExecution::handleCycle(const CFBasicBlockGWTOCycle *cycle) } } -bool AbstractExecution::widenFixpointPass(const CFBasicBlockNode* cycle_head, IntervalExeState& pre_es) +bool AbstractExecution::widenFixpointPass(const ICFGNode* cycle_head, IntervalExeState& pre_es) { // increasing iterations IntervalExeState new_pre_es = pre_es.widening(_postES[cycle_head]); @@ -848,7 +836,7 @@ bool AbstractExecution::widenFixpointPass(const CFBasicBlockNode* cycle_head, In } } -bool AbstractExecution::narrowFixpointPass(const SVF::CFBasicBlockNode *cycle_head, SVF::IntervalExeState &pre_es) +bool AbstractExecution::narrowFixpointPass(const SVF::ICFGNode *cycle_head, SVF::IntervalExeState &pre_es) { // decreasing iterations IntervalExeState new_pre_es = pre_es.narrowing(_postES[cycle_head]); @@ -875,16 +863,16 @@ bool AbstractExecution::narrowFixpointPass(const SVF::CFBasicBlockNode *cycle_he void AbstractExecution::handleFunc(const SVFFunction *func) { _stat->getFunctionTrace()++; - CFBasicBlockGWTO* wto = _funcToWTO[func]; + ICFGWTO* wto = _funcToWTO[func]; // set function entry ES for (auto it = wto->begin(); it!= wto->end(); ++it) { - const CFBasicBlockGWTOComp* cur = *it; - if (const CFBasicBlockGWTONode* vertex = SVFUtil::dyn_cast(cur)) + const ICFGWTOComp* cur = *it; + if (const ICFGWTONode* vertex = SVFUtil::dyn_cast(cur)) { - handleBlock(vertex->node()); + handleWTONode(vertex->node()); } - else if (const CFBasicBlockGWTOCycle* cycle = SVFUtil::dyn_cast(cur)) + else if (const ICFGWTOCycle* cycle = SVFUtil::dyn_cast(cur)) { handleCycle(cycle); } @@ -895,7 +883,6 @@ void AbstractExecution::handleFunc(const SVFFunction *func) } } - void AbstractExecution::handleSVFStatement(const SVFStmt *stmt) { if (const AddrStmt *addr = SVFUtil::dyn_cast(stmt)) @@ -1342,6 +1329,7 @@ void AEAPI::checkPointAllSet() { SVFUtil::errs() << SVFUtil::sucMsg(call->toString() + "\n"); } + assert(false); } } diff --git a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp index 62fe9ed49..4b94b279c 100644 --- a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +++ b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp @@ -492,106 +492,6 @@ void BufOverflowCheckerAPI::handleExtAPI(const CallICFGNode *call) return; } - -void BufOverflowChecker::handleICFGNode(const SVF::ICFGNode *node) -{ - AbstractExecution::handleICFGNode(node); - detectBufOverflow(node); -} - -// -bool BufOverflowChecker::detectBufOverflow(const ICFGNode *node) -{ - - auto *extapi = SVFUtil::dyn_cast(_api); - for (auto* stmt: node->getSVFStmts()) - { - if (const GepStmt *gep = SVFUtil::dyn_cast(stmt)) - { - const SVFVar* gepRhs = gep->getRHSVar(); - if (const SVFInstruction* inst = SVFUtil::dyn_cast(gepRhs->getValue())) - { - const ICFGNode* icfgNode = _svfir->getICFG()->getICFGNode(inst); - for (const SVFStmt* stmt2: icfgNode->getSVFStmts()) - { - if (const GepStmt *gep2 = SVFUtil::dyn_cast(stmt2)) - { - return extapi->canSafelyAccessMemory(gep2->getLHSVar()->getValue(), IntervalValue(0, 0), node); - } - } - } - } - else if (const LoadStmt* load = SVFUtil::dyn_cast(stmt)) - { - if (_svfir2ExeState->inVarToAddrsTable(load->getRHSVarID())) - { - ExeState::Addrs Addrs = _svfir2ExeState->getAddrs(load->getRHSVarID()); - for (auto vaddr: Addrs) - { - u32_t objId = _svfir2ExeState->getInternalID(vaddr); - if (extapi->_addrToGep.find(objId) != extapi->_addrToGep.end()) - { - const GepStmt* gep = extapi->_addrToGep.at(objId); - return extapi->canSafelyAccessMemory(gep->getLHSVar()->getValue(), IntervalValue(0, 0), node); - } - } - } - } - else if (const StoreStmt* store = SVFUtil::dyn_cast(stmt)) - { - if (_svfir2ExeState->inVarToAddrsTable(store->getLHSVarID())) - { - ExeState::Addrs Addrs = _svfir2ExeState->getAddrs(store->getLHSVarID()); - for (auto vaddr: Addrs) - { - u32_t objId = _svfir2ExeState->getInternalID(vaddr); - if (extapi->_addrToGep.find(objId) != extapi->_addrToGep.end()) - { - const GepStmt* gep = extapi->_addrToGep.at(objId); - return extapi->canSafelyAccessMemory(gep->getLHSVar()->getValue(), IntervalValue(0, 0), node); - } - } - } - } - } - return true; -} - -void BufOverflowChecker::addBugToRecoder(const BufOverflowException& e, const ICFGNode* node) -{ - const SVFInstruction* inst = nullptr; - if (const CallICFGNode* call = SVFUtil::dyn_cast(node)) - { - inst = call->getCallSite(); - } - else - { - inst = node->getSVFStmts().back()->getInst(); - } - GenericBug::EventStack eventStack; - SVFBugEvent sourceInstEvent(SVFBugEvent::EventType::SourceInst, inst); - for (const auto &callsite: _callSiteStack) - { - SVFBugEvent callSiteEvent(SVFBugEvent::EventType::CallSite, callsite->getCallSite()); - eventStack.push_back(callSiteEvent); - } - eventStack.push_back(sourceInstEvent); - if (eventStack.size() == 0) return; - std::string loc = eventStack.back().getEventLoc(); - if (_bugLoc.find(loc) != _bugLoc.end()) - { - return; - } - else - { - _bugLoc.insert(loc); - } - _recoder.addAbsExecBug(GenericBug::FULLBUFOVERFLOW, eventStack, e.getAllocLb(), e.getAllocUb(), e.getAccessLb(), - e.getAccessUb()); - _nodeToBugInfo[node] = e.what(); -} - - bool BufOverflowCheckerAPI::canSafelyAccessMemory(const SVFValue *value, const IntervalValue &len, const ICFGNode *curNode) { BufOverflowChecker* ae = static_cast(this->_ae); @@ -685,7 +585,7 @@ bool BufOverflowCheckerAPI::canSafelyAccessMemory(const SVFValue *value, const I if (const SVFConstantInt *op = SVFUtil::dyn_cast(idxValue)) { u32_t lb = (double) Options::MaxFieldLimit() / arrElemSize >= op->getSExtValue() ? - op->getSExtValue() * arrElemSize : Options::MaxFieldLimit(); + op->getSExtValue() * arrElemSize : Options::MaxFieldLimit(); gepArrTotalByte = gepArrTotalByte + IntervalValue(lb, lb); } else @@ -700,12 +600,12 @@ bool BufOverflowCheckerAPI::canSafelyAccessMemory(const SVFValue *value, const I { u32_t ub = (idxVal.ub().getNumeral() < 0) ? 0 : (double) Options::MaxFieldLimit() / arrElemSize >= - idxVal.ub().getNumeral() ? - arrElemSize * idxVal.ub().getNumeral() : Options::MaxFieldLimit(); + idxVal.ub().getNumeral() ? + arrElemSize * idxVal.ub().getNumeral() : Options::MaxFieldLimit(); u32_t lb = (idxVal.lb().getNumeral() < 0) ? 0 : ((double) Options::MaxFieldLimit() / arrElemSize >= idxVal.lb().getNumeral()) ? - arrElemSize * idxVal.lb().getNumeral() : Options::MaxFieldLimit(); + arrElemSize * idxVal.lb().getNumeral() : Options::MaxFieldLimit(); gepArrTotalByte = gepArrTotalByte + IntervalValue(lb, ub); } } @@ -756,7 +656,7 @@ bool BufOverflowCheckerAPI::canSafelyAccessMemory(const SVFValue *value, const I // addrStmt is source node. u32_t arr_type_size = getAllocaInstByteSize(addr); if (total_bytes.ub().getNumeral() >= arr_type_size || - total_bytes.lb().getNumeral() < 0) + total_bytes.lb().getNumeral() < 0) { std::string msg = "Buffer overflow!! Accessing buffer range: " + IntervalToIntStr(total_bytes) + @@ -836,4 +736,104 @@ bool BufOverflowCheckerAPI::canSafelyAccessMemory(const SVFValue *value, const I return true; } + + +void BufOverflowChecker::handleICFGNode(const SVF::ICFGNode *node) +{ + AbstractExecution::handleICFGNode(node); + detectBufOverflow(node); +} + +// +bool BufOverflowChecker::detectBufOverflow(const ICFGNode *node) +{ + + auto *extapi = SVFUtil::dyn_cast(_api); + for (auto* stmt: node->getSVFStmts()) + { + if (const GepStmt *gep = SVFUtil::dyn_cast(stmt)) + { + const SVFVar* gepRhs = gep->getRHSVar(); + if (const SVFInstruction* inst = SVFUtil::dyn_cast(gepRhs->getValue())) + { + const ICFGNode* icfgNode = _svfir->getICFG()->getICFGNode(inst); + for (const SVFStmt* stmt2: icfgNode->getSVFStmts()) + { + if (const GepStmt *gep2 = SVFUtil::dyn_cast(stmt2)) + { + return extapi->canSafelyAccessMemory(gep2->getLHSVar()->getValue(), IntervalValue(0, 0), node); + } + } + } + } + else if (const LoadStmt* load = SVFUtil::dyn_cast(stmt)) + { + if (_svfir2ExeState->inVarToAddrsTable(load->getRHSVarID())) + { + ExeState::Addrs Addrs = _svfir2ExeState->getAddrs(load->getRHSVarID()); + for (auto vaddr: Addrs) + { + u32_t objId = _svfir2ExeState->getInternalID(vaddr); + if (extapi->_addrToGep.find(objId) != extapi->_addrToGep.end()) + { + const GepStmt* gep = extapi->_addrToGep.at(objId); + return extapi->canSafelyAccessMemory(gep->getLHSVar()->getValue(), IntervalValue(0, 0), node); + } + } + } + } + else if (const StoreStmt* store = SVFUtil::dyn_cast(stmt)) + { + if (_svfir2ExeState->inVarToAddrsTable(store->getLHSVarID())) + { + ExeState::Addrs Addrs = _svfir2ExeState->getAddrs(store->getLHSVarID()); + for (auto vaddr: Addrs) + { + u32_t objId = _svfir2ExeState->getInternalID(vaddr); + if (extapi->_addrToGep.find(objId) != extapi->_addrToGep.end()) + { + const GepStmt* gep = extapi->_addrToGep.at(objId); + return extapi->canSafelyAccessMemory(gep->getLHSVar()->getValue(), IntervalValue(0, 0), node); + } + } + } + } + } + return true; +} + +void BufOverflowChecker::addBugToRecoder(const BufOverflowException& e, const ICFGNode* node) +{ + const SVFInstruction* inst = nullptr; + if (const CallICFGNode* call = SVFUtil::dyn_cast(node)) + { + inst = call->getCallSite(); + } + else + { + inst = node->getSVFStmts().back()->getInst(); + } + GenericBug::EventStack eventStack; + SVFBugEvent sourceInstEvent(SVFBugEvent::EventType::SourceInst, inst); + for (const auto &callsite: _callSiteStack) + { + SVFBugEvent callSiteEvent(SVFBugEvent::EventType::CallSite, callsite->getCallSite()); + eventStack.push_back(callSiteEvent); + } + eventStack.push_back(sourceInstEvent); + if (eventStack.size() == 0) return; + std::string loc = eventStack.back().getEventLoc(); + if (_bugLoc.find(loc) != _bugLoc.end()) + { + return; + } + else + { + _bugLoc.insert(loc); + } + _recoder.addAbsExecBug(GenericBug::FULLBUFOVERFLOW, eventStack, e.getAllocLb(), e.getAllocUb(), e.getAccessLb(), + e.getAccessUb()); + _nodeToBugInfo[node] = e.what(); +} + } diff --git a/svf/lib/Graphs/CFBasicBlockG.cpp b/svf/lib/Graphs/CFBasicBlockG.cpp deleted file mode 100644 index 548e78d0a..000000000 --- a/svf/lib/Graphs/CFBasicBlockG.cpp +++ /dev/null @@ -1,80 +0,0 @@ -//===- CFBasicBlockG.cpp ----------------------------------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero 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 Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -// -//===----------------------------------------------------------------------===// - -/* - * CFBasicBlockG.cpp - * - * Created on: 24 Dec. 2022 - * Author: Xiao, Jiawei - */ - -#include "Graphs/CFBasicBlockG.h" -#include "SVFIR/SVFIR.h" - -namespace SVF -{ - -const std::string CFBasicBlockNode::toString() const -{ - std::string rawStr; - std::stringstream stringstream(rawStr); - stringstream << "Block Name: " << getName() << "\n"; - for (const auto &icfgNode: _icfgNodes) - { - stringstream << icfgNode->toString() << "\n"; - } - return stringstream.str(); -} - -CFBasicBlockEdge* CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst, const ICFGEdge* icfgEdge) -{ - CFBasicBlockEdge *edge = nullptr; - size_t counter = 0; - for (auto iter = src->OutEdgeBegin(); - iter != src->OutEdgeEnd(); ++iter) - { - if ((*iter)->getDstID() == dst->getId() && (*iter)->getICFGEdge() == icfgEdge) - { - counter++; - edge = (*iter); - } - } - assert(counter <= 1 && "there's more than one edge between two nodes"); - return edge; -} - -std::vector CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst) -{ - std::vector edges; - for (auto iter = src->OutEdgeBegin(); - iter != src->OutEdgeEnd(); ++iter) - { - if ((*iter)->getDstID() == dst->getId()) - { - edges.push_back(*iter); - } - } - return SVFUtil::move(edges); -} - -} - diff --git a/svf/lib/Util/CFBasicBlockGBuilder.cpp b/svf/lib/Util/CFBasicBlockGBuilder.cpp deleted file mode 100644 index d0d2498d6..000000000 --- a/svf/lib/Util/CFBasicBlockGBuilder.cpp +++ /dev/null @@ -1,258 +0,0 @@ -//===- CFBasicBlockGBuilder.cpp ----------------------------------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero 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 Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -// -//===----------------------------------------------------------------------===// - -/* - * CFBasicBlockGBuilder.cpp - * - * Created on: 17 Oct. 2023 - * Author: Xiao, Jiawei - */ -#include "Util/CFBasicBlockGBuilder.h" - -#include - -namespace SVF -{ - -/** - * Initialize Control Flow Basic Block Graph (CFBasicBlockG) nodes based on the provided Interprocedural Control Flow Graph (ICFG). - * - * @param icfg The Interprocedural Control Flow Graph (ICFG) to initialize from. - * @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects. - */ -void CFBasicBlockGBuilder::initCFBasicBlockGNodes(ICFG *icfg, - Map> &bbToNodes) -{ - for (const auto &func : *PAG::getPAG()->getModule()) - { - for(const auto& bb: *func) - { - for(const auto& inst: *bb) - { - if(SVFUtil::isIntrinsicInst(inst)) continue; - const ICFGNode* icfgNode = icfg->getICFGNode(inst); - if (const CallICFGNode *callNode = SVFUtil::dyn_cast(icfgNode)) - { - // Create a new CFBasicBlockNode for the CallICFGNode - CFBasicBlockNode* pNode = new CFBasicBlockNode({callNode}); - bbToNodes[bb].push_back(pNode); - _CFBasicBlockG->addCFBBNode(pNode); - - // Create a new CFBasicBlockNode for the corresponding RetICFGNode - auto *retNode = new CFBasicBlockNode({callNode->getRetICFGNode()}); - bbToNodes[bb].push_back(retNode); - _CFBasicBlockG->addCFBBNode(retNode); - } - else - { - if (bbToNodes.find(bb) == bbToNodes.end()) - { - // Create a new CFBasicBlockNode for the non-CallICFGNode - CFBasicBlockNode* pNode = new CFBasicBlockNode({icfgNode}); - bbToNodes[bb] = {pNode}; - _CFBasicBlockG->addCFBBNode(pNode); - } - else - { - CFBasicBlockNode* pNode = bbToNodes[bb].back(); - if (!SVFUtil::isa(pNode->getICFGNodes()[0])) - { - // Add the non-CallICFGNode to the existing CFBasicBlockNode - pNode->addNode(icfgNode); - } - else - { - // Create a new CFBasicBlockNode for the non-CallICFGNode - pNode = new CFBasicBlockNode({icfgNode}); - bbToNodes[bb].push_back(pNode); - _CFBasicBlockG->addCFBBNode(pNode); - } - } - } - } - } - - if(const FunEntryICFGNode* funEntryNode = icfg->getFunEntryICFGNode(func)) - { - if(const SVFBasicBlock* bb = funEntryNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - CFBasicBlockNode* pNode = new CFBasicBlockNode({funEntryNode}); - nodes.insert(nodes.begin(), pNode); - _CFBasicBlockG->addCFBBNode(pNode); - } - } - - if(const FunExitICFGNode* funExitNode = icfg->getFunExitICFGNode(func)) - { - if(const SVFBasicBlock* bb = funExitNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - CFBasicBlockNode* pNode = new CFBasicBlockNode({funExitNode}); - nodes.push_back(pNode); - _CFBasicBlockG->addCFBBNode(pNode); - } - } - } -} - - -/** - * Add inter-BasicBlock edges to the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG). - * - * @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from. - * @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects. - */ -void CFBasicBlockGBuilder::addInterBBEdge(ICFG *icfg, - Map> &bbToNodes) -{ - // Connect inter-BB BBNodes - for (const auto &node : *icfg) - { - for (const auto &succ : node.second->getOutEdges()) - { - // Check if it's an intraCFGEdge in case of recursive functions - // if recursive functions, node_fun == succ_fun but they are different call context - // edges related to recursive functions would be added in addInterProceduralEdge() - if (succ->isIntraCFGEdge()) - { - const SVFFunction *node_fun = node.second->getFun(); - const SVFFunction *succ_fun = succ->getDstNode()->getFun(); - const SVFBasicBlock *node_bb = node.second->getBB(); - const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); - if (node_fun == succ_fun) - { - if (node_bb != succ_bb) - { - // Create a new CFBasicBlockEdge connecting the last node of the source BB - // and the first node of the destination BB - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge( - bbToNodes[node_bb].back(), - bbToNodes[succ_bb].front(), succ); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - } - } - } - } -} - -/** - * Add intra-BasicBlock edges to the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG). - * - * @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from. - * @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects. - */ -void CFBasicBlockGBuilder::addIntraBBEdge(ICFG *icfg, - Map> &bbToNodes) -{ - // Connect intra-BB BBNodes - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) - { - // Check if an intraCFGEdge exists between the last node of the source BB and the first node of the destination BB - if (ICFGEdge *icfgEdge = icfg->getICFGEdge( - const_cast(bbNodes.second[i]->getICFGNodes().back()), - const_cast(bbNodes.second[i + 1]->getICFGNodes().front()), - ICFGEdge::IntraCF)) - { - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i], bbNodes.second[i + 1], icfgEdge); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - else - { - // No intra-procedural edge found, possibly an external API call - } - } - } -} - -/** - * Add inter-procedural edges between CFBasicBlockNodes based on the provided Interprocedural Control Flow Graph (ICFG). - * - * @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from. - * @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects. - */ -void CFBasicBlockGBuilder::addInterProceduralEdge(ICFG *icfg, - Map> &bbToNodes) -{ - // Connect inter-procedural BBNodes - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size(); ++i) - { - if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i]->getICFGNodes().front())) - { - for (const auto &icfgEdge : callICFGNode->getOutEdges()) - { - if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) - { - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i], - bbToNodes[callEdge->getDstNode()->getBB()].front(), - callEdge); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - } - } - else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i]->getICFGNodes().front())) - { - for (const auto &icfgEdge : retICFGNode->getInEdges()) - { - if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) - { - // no return function - if(!retEdge->getSrcNode()->getFun()->hasReturn()) continue; - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNodes[retEdge->getSrcNode()->getBB()].back(), - bbNodes.second[i], - retEdge); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - } - } - else - { - // Other nodes are intra-procedural - } - } - } -} - -/** - * Build the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG). - * - * @param icfg The Interprocedural Control Flow Graph (ICFG) to extract control flow information from. - */ -void CFBasicBlockGBuilder::build(ICFG *icfg) -{ - _CFBasicBlockG = new CFBasicBlockGraph(); - Map> bbToNodes; - - initCFBasicBlockGNodes(icfg, bbToNodes); - addInterBBEdge(icfg, bbToNodes); - addIntraBBEdge(icfg, bbToNodes); - addInterProceduralEdge(icfg, bbToNodes); -} - -} \ No newline at end of file