Static Value-Flow Analysis
Loading...
Searching...
No Matches
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 on: Jan 10, 2024
26// Author: Xiao Cheng, Jiawei Wang
27// The implementation is based on
28// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
29// 46th International Conference on Software Engineering. (ICSE24)
30//
31#pragma once
33#include "AE/Core/ICFGWTO.h"
36#include "AE/Svfexe/AbsExtAPI.h"
37#include "AE/Svfexe/AEStat.h"
38#include "Util/SVFBugReport.h"
39#include "Graphs/SCC.h"
40#include "Graphs/CallGraph.h"
41#include <deque>
42
43namespace SVF
44{
45class AbstractInterpretation;
46class AbsExtAPI;
47class AEStat;
48class AEAPI;
49
50template<typename T> class FILOWorkList;
51
54{
55 friend class AEStat;
56 friend class AEAPI;
57 friend class BufOverflowDetector;
59
60public:
61 /*
62 * For recursive test case
63 * int demo(int a) {
64 if (a >= 10000)
65 return a;
66 demo(a+1);
67 }
68
69 int main() {
70 int result = demo(0);
71 }
72 * if set TOP, result = [-oo, +oo] since the return value, and any stored object pointed by q at *q = p in recursive functions will be set to the top value.
73 * if set WIDEN_ONLY, result = [10000, +oo] since only widening is applied at the cycle head of recursive functions without narrowing.
74 * if set WIDEN_NARROW, result = [10000, 10000] since both widening and narrowing are applied at the cycle head of recursive functions.
75 * */
82
85
86 virtual void runOnModule(ICFG* icfg);
87
90
92 void analyse();
93
96
98 std::deque<const FunObjVar*> collectProgEntryFuns();
99
100
102 {
104 return instance;
105 }
106
107 void addDetector(std::unique_ptr<AEDetector> detector)
108 {
109 detectors.push_back(std::move(detector));
110 }
111
113 inline const SVFVar* getSVFVar(NodeID varId) const
114 {
115 return svfir->getSVFVar(varId);
116 }
117
120
122 const AbstractValue& getAbstractValue(const ICFGNode* node, const ObjVar* var);
123
125 const AbstractValue& getAbstractValue(const ICFGNode* node, const SVFVar* var);
126
128 void updateAbstractValue(const ValVar* var, const AbstractValue& val);
129
131 void updateAbstractValue(const ICFGNode* node, const ObjVar* var, const AbstractValue& val);
132
134 void updateAbstractValue(const ICFGNode* node, const SVFVar* var, const AbstractValue& val);
135
137 void propagateObjVarAbsVal(const ObjVar* var, const ICFGNode* defSite);
138
141
143 bool hasAbstractState(const ICFGNode* node);
144
147
150
153
154
155private:
157 virtual void handleGlobalNode();
158
160 void propagateToSuccessor(const ICFGNode* node,
161 const Set<const ICFGNode*>* withinSet = nullptr);
162
165
167 virtual void handleCallSite(const ICFGNode* node);
168
170 virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller = nullptr);
171
173 void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller = nullptr);
174
176 bool handleICFGNode(const ICFGNode* node);
177
179 virtual void handleSVFStatement(const SVFStmt* stmt);
180
182 virtual void setTopToObjInRecursion(const CallICFGNode* callnode);
183
187
190
191 void updateStateOnAddr(const AddrStmt *addr);
192
194
195 void updateStateOnCmp(const CmpStmt *cmp);
196
197 void updateStateOnLoad(const LoadStmt *load);
198
199 void updateStateOnStore(const StoreStmt *store);
200
201 void updateStateOnCopy(const CopyStmt *copy);
202
203 void updateStateOnCall(const CallPE *callPE);
204
205 void updateStateOnRet(const RetPE *retPE);
206
207 void updateStateOnGep(const GepStmt *gep);
208
210
211 void updateStateOnPhi(const PhiStmt *phi);
212
213
217 AEAPI* api{nullptr};
218
222
224
226 {
227 return utils;
228 }
229
230 // helper functions in handleCallSite
231 virtual bool isExtCall(const CallICFGNode* callNode);
232 virtual void handleExtCall(const CallICFGNode* callNode);
233 virtual bool isRecursiveFun(const FunObjVar* fun);
234 virtual void handleRecursiveCall(const CallICFGNode *callNode);
235 virtual bool isRecursiveCallSite(const CallICFGNode* callNode, const FunObjVar *);
236 virtual void handleFunCall(const CallICFGNode* callNode);
237
240 bool shouldApplyNarrowing(const FunObjVar* fun);
241
242 // there data should be shared with subclasses
243 Map<std::string, std::function<void(const CallICFGNode*)>> func_map;
244
245 Map<const ICFGNode*, AbstractState> abstractTrace; // abstract states for nodes (pre-state before execution, post-state after)
246 Set<const ICFGNode*> allAnalyzedNodes; // All nodes ever analyzed (across all entry points)
247 std::string moduleName;
248
249 std::vector<std::unique_ptr<AEDetector>> detectors;
251
252 // according to varieties of cmp insts,
253 // maybe var X var, var X const, const X var, const X const
254 // we accept 'var X const' 'var X var' 'const X const'
255 // if 'const X var', we need to reverse op0 op1 and its predicate 'var X' const'
256 // X' is reverse predicate of X
257 // == -> !=, != -> ==, > -> <=, >= -> <, < -> >=, <= -> >
258
278
279
299
300};
301}
copy
Definition cJSON.cpp:414
AEStat: Statistic for AE.
Definition AEStat.h:36
Handles external API calls and manages abstract states.
Definition AbsExtAPI.h:44
AbstractInterpretation is same as Abstract Execution.
void updateStateOnCall(const CallPE *callPE)
const FunObjVar * getCallee(const CallICFGNode *callNode)
Get callee function: directly for direct calls, via pointer analysis for indirect calls.
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
void updateStateOnStore(const StoreStmt *store)
virtual void handleFunCall(const CallICFGNode *callNode)
void analyzeFromAllProgEntries()
Analyze all entry points (functions without callers)
static AbstractInterpretation & getAEInstance()
void updateStateOnGep(const GepStmt *gep)
virtual void handleGlobalNode()
Initialize abstract state for the global ICFG node and process global statements.
void handleFunction(const ICFGNode *funEntry, const CallICFGNode *caller=nullptr)
Handle a function body via worklist-driven WTO traversal starting from funEntry.
virtual bool isExtCall(const CallICFGNode *callNode)
void updateAbstractValue(const ValVar *var, const AbstractValue &val)
Set abstract value for a top-level variable at a given ICFG node.
AbstractState & getAbstractState(const ICFGNode *node)
Retrieve the abstract state from the trace for a given ICFG node; asserts if no trace exists.
void updateStateOnPhi(const PhiStmt *phi)
bool handleICFGNode(const ICFGNode *node)
Handle an ICFG node: execute statements; return true if state changed.
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
Check if the branch on intraEdge is feasible under abstract state as.
std::vector< std::unique_ptr< AEDetector > > detectors
void addDetector(std::unique_ptr< AEDetector > detector)
virtual void handleExtCall(const CallICFGNode *callNode)
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
Check if switch branch with case value succ is feasible; refine intervals in as accordingly.
void updateStateOnSelect(const SelectStmt *select)
virtual void handleSVFStatement(const SVFStmt *stmt)
Dispatch an SVF statement (Addr/Binary/Cmp/Load/Store/Copy/Gep/Select/Phi/Call/Ret) to its handler.
bool skipRecursiveCall(const CallICFGNode *callNode)
Skip recursive callsites (within SCC); entry calls from outside SCC are not skipped.
bool hasAbstractState(const ICFGNode *node)
Check if an abstract state exists in the trace for a given ICFG node.
SVFIR * svfir
protected data members, also used in subclasses
virtual void runOnModule(ICFG *icfg)
virtual bool isRecursiveCallSite(const CallICFGNode *callNode, const FunObjVar *)
Check if caller and callee are in the same CallGraph SCC (i.e. a recursive callsite)
bool shouldApplyNarrowing(const FunObjVar *fun)
Check if narrowing should be applied: always for regular loops, mode-dependent for recursion.
virtual bool isRecursiveFun(const FunObjVar *fun)
Check if a function is recursive (part of a call graph SCC)
void updateStateOnAddr(const AddrStmt *addr)
virtual ~AbstractInterpretation()
Destructor.
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
Check if cmpStmt with successor value succ is feasible; refine intervals in as accordingly.
virtual void handleCallSite(const ICFGNode *node)
Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling.
void updateStateOnRet(const RetPE *retPE)
void updateStateOnCopy(const CopyStmt *copy)
void propagateObjVarAbsVal(const ObjVar *var, const ICFGNode *defSite)
Propagate an ObjVar's abstract value from defSite to all its use-site ICFGNodes via SVFG.
std::deque< const FunObjVar * > collectProgEntryFuns()
Get all entry point functions (functions without callers)
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
Set< const ICFGNode * > allAnalyzedNodes
virtual void setTopToObjInRecursion(const CallICFGNode *callnode)
Set all store targets and return value to TOP for a recursive call node.
virtual void handleRecursiveCall(const CallICFGNode *callNode)
Handle recursive call in TOP mode: set all stores and return value to TOP.
virtual void handleLoopOrRecursion(const ICFGCycleWTO *cycle, const CallICFGNode *caller=nullptr)
Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration.
Map< s32_t, s32_t > _switch_lhsrhs_predicate
const SVFVar * getSVFVar(NodeID varId) const
Retrieve SVFVar given its ID; asserts if no such variable exists.
void updateStateOnCmp(const CmpStmt *cmp)
void propagateToSuccessor(const ICFGNode *node, const Set< const ICFGNode * > *withinSet=nullptr)
Propagate the post-state of a node to all its intra-procedural successors.
const AbstractValue & getAbstractValue(const ValVar *var)
Retrieve abstract value for a top-level variable at a given ICFG node.
Detector for identifying buffer overflow issues.
Definition AEDetector.h:136
@ 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
@ 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
@ ICMP_ULT
unsigned less than
@ 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
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:131
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:56
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed long long s64_t
Definition GeneralType.h:50