Static Value-Flow Analysis
AbstractInterpretation.h
Go to the documentation of this file.
1 //===- AbstractInterpretation.h -- Abstract Execution----------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 
24 //
25 // Created by Jiawei Wang on 2024/1/10.
26 // The implementation is based on
27 // Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
28 // 46th International Conference on Software Engineering. (ICSE24)
29 //
30 #pragma once
31 #include "AE/Core/AbstractState.h"
32 #include "AE/Core/ICFGWTO.h"
33 #include "AE/Svfexe/AEDetector.h"
34 #include "AE/Svfexe/AbsExtAPI.h"
35 #include "Util/SVFBugReport.h"
36 #include "WPA/Andersen.h"
37 
38 namespace SVF
39 {
40 class AbstractInterpretation;
41 class AbsExtAPI;
42 class AEStat;
43 class AEAPI;
44 
45 template<typename T> class FILOWorkList;
46 
48 class AEStat : public SVFStat
49 {
50 public:
51  void countStateSize();
53  {
54  startTime = getClk(true);
55  }
57  {
58  }
60  {
61  u32_t vmrss, vmsize;
62  return SVFUtil::getMemoryUsageKB(&vmrss, &vmsize) ? std::to_string(vmsize) + "KB" : "cannot read memory usage";
63  }
64 
65  void finializeStat();
66  void performStat() override;
67 
68 public:
73 
74 
76  {
77  if (generalNumMap.count("Function_Trace") == 0)
78  {
79  generalNumMap["Function_Trace"] = 0;
80  }
81  return generalNumMap["Function_Trace"];
82  }
84  {
85  if (generalNumMap.count("Block_Trace") == 0)
86  {
87  generalNumMap["Block_Trace"] = 0;
88  }
89  return generalNumMap["Block_Trace"];
90  }
92  {
93  if (generalNumMap.count("ICFG_Node_Trace") == 0)
94  {
95  generalNumMap["ICFG_Node_Trace"] = 0;
96  }
97  return generalNumMap["ICFG_Node_Trace"];
98  }
99 };
100 
103 {
104  friend class AEStat;
105  friend class AEAPI;
106  friend class BufOverflowDetector;
107 
108 public:
112 
113  virtual void runOnModule(ICFG* icfg);
114 
116  virtual ~AbstractInterpretation();
117 
119  void analyse();
120 
122  {
123  static AbstractInterpretation instance;
124  return instance;
125  }
126 
127  void addDetector(std::unique_ptr<AEDetector> detector)
128  {
129  detectors.push_back(std::move(detector));
130  }
131 
133 
134 private:
136  virtual void handleGlobalNode();
137 
139  void initWTO();
140 
147  bool mergeStatesFromPredecessors(const ICFGNode * icfgNode);
148 
155  bool isBranchFeasible(const IntraCFGEdge* intraEdge, AbstractState& as);
156 
162  virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto);
163 
169  virtual void handleCallSite(const ICFGNode* node);
170 
176  virtual void handleCycleWTO(const ICFGCycleWTO* cycle);
177 
178  void handleWTOComponents(const std::list<const ICFGWTOComp*>& wtoComps);
179 
180  void handleWTOComponent(const ICFGWTOComp* wtoComp);
181 
182 
188  virtual void handleSVFStatement(const SVFStmt* stmt);
189 
195  virtual void SkipRecursiveCall(const CallICFGNode* callnode);
196 
197 
205  bool isCmpBranchFeasible(const CmpStmt* cmpStmt, s64_t succ,
206  AbstractState& as);
207 
215  bool isSwitchBranchFeasible(const SVFVar* var, s64_t succ,
216  AbstractState& as);
217 
218 
219  void collectCheckPoint();
220  void checkPointAllSet();
221 
222  void updateStateOnAddr(const AddrStmt *addr);
223 
224  void updateStateOnBinary(const BinaryOPStmt *binary);
225 
226  void updateStateOnCmp(const CmpStmt *cmp);
227 
228  void updateStateOnLoad(const LoadStmt *load);
229 
230  void updateStateOnStore(const StoreStmt *store);
231 
232  void updateStateOnCopy(const CopyStmt *copy);
233 
234  void updateStateOnCall(const CallPE *callPE);
235 
236  void updateStateOnRet(const RetPE *retPE);
237 
238  void updateStateOnGep(const GepStmt *gep);
239 
240  void updateStateOnSelect(const SelectStmt *select);
241 
242  void updateStateOnPhi(const PhiStmt *phi);
243 
244 
248  AEAPI* api{nullptr};
249 
252 
253  std::vector<const CallICFGNode*> callSiteStack;
256 
257 
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  }
270 
271  bool hasAbsStateFromTrace(const ICFGNode* node)
272  {
273  const ICFGNode* repNode = icfg->getRepNode(node);
274  return abstractTrace.count(repNode) != 0;
275  }
276 
278  {
279  return utils;
280  }
281 
282  // helper functions in handleCallSite
283  virtual bool isExtCall(const CallICFGNode* callNode);
284  virtual void extCallPass(const CallICFGNode* callNode);
285  virtual bool isRecursiveCall(const CallICFGNode* callNode);
286  virtual void recursiveCallPass(const CallICFGNode* callNode);
287  virtual bool isDirectCall(const CallICFGNode* callNode);
288  virtual void directCallFunPass(const CallICFGNode* callNode);
289  virtual bool isIndirectCall(const CallICFGNode* callNode);
290  virtual void indirectCallFunPass(const CallICFGNode* callNode);
291 
292  // there data should be shared with subclasses
293  Map<std::string, std::function<void(const CallICFGNode*)>> func_map;
294 
295  Map<const ICFGNode*, AbstractState> abstractTrace; // abstract states immediately after nodes
297 
298  std::vector<std::unique_ptr<AEDetector>> detectors;
300 
301  // according to varieties of cmp insts,
302  // maybe var X var, var X const, const X var, const X const
303  // we accept 'var X const' 'var X var' 'const X const'
304  // if 'const X var', we need to reverse op0 op1 and its predicate 'var X' const'
305  // X' is reverse predicate of X
306  // == -> !=, != -> ==, > -> <=, >= -> <, < -> >=, <= -> >
307 
309  {
310  {CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_ONE}, // == -> !=
311  {CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UNE}, // == -> !=
312  {CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLE}, // > -> <=
313  {CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLT}, // >= -> <
314  {CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGE}, // < -> >=
315  {CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGT}, // <= -> >
316  {CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_OEQ}, // != -> ==
317  {CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UEQ}, // != -> ==
318  {CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_NE}, // == -> !=
319  {CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_EQ}, // != -> ==
320  {CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULE}, // > -> <=
321  {CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGE}, // < -> >=
322  {CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULT}, // >= -> <
323  {CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLE}, // > -> <=
324  {CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGE}, // < -> >=
325  {CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLT}, // >= -> <
326  };
327 
328 
330  {
331  {CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_OEQ}, // == -> ==
332  {CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UEQ}, // == -> ==
333  {CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLT}, // > -> <
334  {CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLE}, // >= -> <=
335  {CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGT}, // < -> >
336  {CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGE}, // <= -> >=
337  {CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_ONE}, // != -> !=
338  {CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UNE}, // != -> !=
339  {CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_EQ}, // == -> ==
340  {CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_NE}, // != -> !=
341  {CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULT}, // > -> <
342  {CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGT}, // < -> >
343  {CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULE}, // >= -> <=
344  {CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLT}, // > -> <
345  {CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGT}, // < -> >
346  {CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLE}, // >= -> <=
347  };
348 
349 };
350 }
copy
Definition: cJSON.cpp:414
const char *const string
Definition: cJSON.h:172
AEStat: Statistic for AE.
std::string memory_usage
std::string memUsage
void performStat() override
u32_t & getFunctionTrace()
AEStat(AbstractInterpretation *ae)
std::string getMemUsage()
AbstractInterpretation * _ae
u32_t & getICFGNodeTrace()
Handles external API calls and manages abstract states.
Definition: AbsExtAPI.h:46
AbstractInterpretation is same as Abstract Execution.
void updateStateOnCall(const CallPE *callPE)
virtual bool isRecursiveCall(const CallICFGNode *callNode)
virtual void recursiveCallPass(const CallICFGNode *callNode)
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
void updateStateOnStore(const StoreStmt *store)
virtual bool isDirectCall(const CallICFGNode *callNode)
bool hasAbsStateFromTrace(const ICFGNode *node)
Map< const SVFFunction *, ICFGWTO * > funcToWTO
virtual void handleCycleWTO(const ICFGCycleWTO *cycle)
handle wto cycle (loop)
void updateStateOnGep(const GepStmt *gep)
virtual void extCallPass(const CallICFGNode *callNode)
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)
virtual void directCallFunPass(const CallICFGNode *callNode)
void handleWTOComponent(const ICFGWTOComp *wtoComp)
virtual bool isExtCall(const CallICFGNode *callNode)
virtual bool isIndirectCall(const CallICFGNode *callNode)
void initWTO()
Mark recursive functions in the call graph.
SCCDetection< PTACallGraph * > CallGraphSCC
void updateStateOnPhi(const PhiStmt *phi)
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
std::vector< std::unique_ptr< AEDetector > > detectors
void addDetector(std::unique_ptr< AEDetector > detector)
Set< const CallICFGNode * > checkpoints
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
Map< s32_t, s32_t > _reverse_predicate
Set< const SVFFunction * > recursiveFuns
void updateStateOnSelect(const SelectStmt *select)
virtual void handleSVFStatement(const SVFStmt *stmt)
virtual void indirectCallFunPass(const CallICFGNode *callNode)
SVFIR * svfir
protected data members, also used in subclasses
virtual void runOnModule(ICFG *icfg)
static AbstractInterpretation & getAEInstance()
void updateStateOnAddr(const AddrStmt *addr)
virtual ~AbstractInterpretation()
Destructor.
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
virtual void handleCallSite(const ICFGNode *node)
void updateStateOnRet(const RetPE *retPE)
void handleWTOComponents(const std::list< const ICFGWTOComp * > &wtoComps)
Hanlde two types of WTO components (singleton and cycle)
void updateStateOnCopy(const CopyStmt *copy)
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
AEAPI * api
Execution State, used to store the Interval Value of every SVF variable.
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
Map< const ICFGNode *, AbstractState > abstractTrace
std::vector< const CallICFGNode * > callSiteStack
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto)
handle instructions in svf basic blocks
Map< s32_t, s32_t > _switch_lhsrhs_predicate
void updateStateOnCmp(const CmpStmt *cmp)
virtual void SkipRecursiveCall(const CallICFGNode *callnode)
Detector for identifying buffer overflow issues.
Definition: AEDetector.h:134
Definition: ICFG.h:48
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition: ICFG.h:246
NUMStatMap generalNumMap
Definition: SVFStat.h:76
double startTime
Definition: SVFStat.h:80
static double getClk(bool mark=false)
Definition: SVFStat.cpp:47
bool getMemoryUsageKB(u32_t *vmrss_kb, u32_t *vmsize_kb)
Get memory usage from system file. Return TRUE if succeed.
Definition: SVFUtil.cpp:177
constexpr std::remove_reference< T >::type && move(T &&t) noexcept
Definition: SVFUtil.h:447
for isBitcode
Definition: BasicTypes.h:68
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
signed s32_t
Definition: GeneralType.h:47
unsigned u32_t
Definition: GeneralType.h:46
signed long long s64_t
Definition: GeneralType.h:49
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96