svf-lib 1.0.2084 → 1.0.2086
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux/Release-build/bin/ae +0 -0
- package/SVF-linux/Release-build/include/AE/Core/AbstractState.h +10 -8
- package/SVF-linux/Release-build/include/AE/Svfexe/AEDetector.h +322 -0
- package/SVF-linux/Release-build/include/AE/Svfexe/AbstractInterpretation.h +30 -66
- package/SVF-linux/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-osx/Release-build/bin/ae +0 -0
- package/SVF-osx/Release-build/bin/cfl +0 -0
- package/SVF-osx/Release-build/bin/dvf +0 -0
- package/SVF-osx/Release-build/bin/llvm2svf +0 -0
- package/SVF-osx/Release-build/bin/mta +0 -0
- package/SVF-osx/Release-build/bin/saber +0 -0
- package/SVF-osx/Release-build/bin/svf-ex +0 -0
- package/SVF-osx/Release-build/bin/wpa +0 -0
- package/SVF-osx/Release-build/include/Graphs/ICFG.h +9 -0
- package/SVF-osx/Release-build/include/MSSA/MemRegion.h +2 -2
- package/SVF-osx/Release-build/include/MTA/MHP.h +1 -2
- package/SVF-osx/Release-build/include/SVF-LLVM/ICFGBuilder.h +16 -6
- package/SVF-osx/Release-build/include/SVF-LLVM/LLVMUtil.h +11 -0
- package/SVF-osx/Release-build/include/SVF-LLVM/SVFIRBuilder.h +2 -2
- package/SVF-osx/Release-build/include/SVFIR/SVFIR.h +1 -1
- package/SVF-osx/Release-build/include/SVFIR/SVFStatements.h +1 -1
- package/SVF-osx/Release-build/include/SVFIR/SVFValue.h +21 -16
- package/SVF-osx/Release-build/include/Util/SVFUtil.h +19 -17
- package/SVF-osx/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-osx/Release-build/lib/libSvfLLVM.a +0 -0
- package/package.json +1 -1
- package/SVF-linux/Release-build/include/AE/Svfexe/BufOverflowChecker.h +0 -216
- package/SVF-linux/Release-build/include/AE/Svfexe/ICFGSimplification.h +0 -44
|
Binary file
|
|
@@ -95,6 +95,8 @@ public:
|
|
|
95
95
|
// storeValue
|
|
96
96
|
void storeValue(NodeID varId, AbstractValue val);
|
|
97
97
|
|
|
98
|
+
u32_t getAllocaInstByteSize(const AddrStmt *addr);
|
|
99
|
+
|
|
98
100
|
|
|
99
101
|
/// The physical address starts with 0x7f...... + idx
|
|
100
102
|
static inline u32_t getVirtualMemAddress(u32_t idx)
|
|
@@ -281,13 +283,14 @@ public:
|
|
|
281
283
|
/// domain meet with other, important! other widen this.
|
|
282
284
|
void meetWith(const AbstractState&other);
|
|
283
285
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
/**
|
|
287
|
+
* if this NodeID in SVFIR is a pointer, get the pointee type
|
|
288
|
+
* e.g arr = (int*) malloc(10*sizeof(int))
|
|
289
|
+
* getPointeeType(arr) -> return int
|
|
290
|
+
* we can set arr[0]='c', arr[1]='c', arr[2]='\0'
|
|
291
|
+
* @param call callnode of memset like api
|
|
292
|
+
*/
|
|
293
|
+
const SVFType* getPointeeElement(NodeID id);
|
|
291
294
|
|
|
292
295
|
|
|
293
296
|
u32_t hash() const;
|
|
@@ -395,7 +398,6 @@ public:
|
|
|
395
398
|
_varToAbsVal.clear();
|
|
396
399
|
}
|
|
397
400
|
|
|
398
|
-
|
|
399
401
|
};
|
|
400
402
|
|
|
401
403
|
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
//===- AEDetector.h -- Vulnerability Detectors---------------------------------//
|
|
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/8/20.
|
|
26
|
+
//
|
|
27
|
+
#pragma once
|
|
28
|
+
#include <SVFIR/SVFIR.h>
|
|
29
|
+
#include <AE/Core/AbstractState.h>
|
|
30
|
+
#include "Util/SVFBugReport.h"
|
|
31
|
+
|
|
32
|
+
namespace SVF
|
|
33
|
+
{
|
|
34
|
+
/**
|
|
35
|
+
* @class AEDetector
|
|
36
|
+
* @brief Base class for all detectors.
|
|
37
|
+
*/
|
|
38
|
+
class AEDetector
|
|
39
|
+
{
|
|
40
|
+
public:
|
|
41
|
+
/**
|
|
42
|
+
* @enum DetectorKind
|
|
43
|
+
* @brief Enumerates the types of detectors available.
|
|
44
|
+
*/
|
|
45
|
+
enum DetectorKind
|
|
46
|
+
{
|
|
47
|
+
BUF_OVERFLOW, ///< Detector for buffer overflow issues.
|
|
48
|
+
UNKNOWN, ///< Default type if the kind is not specified.
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @brief Constructor initializes the detector kind to UNKNOWN.
|
|
53
|
+
*/
|
|
54
|
+
AEDetector(): kind(UNKNOWN) {}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @brief Virtual destructor for safe polymorphic use.
|
|
58
|
+
*/
|
|
59
|
+
virtual ~AEDetector() = default;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @brief Check if the detector is of the UNKNOWN kind.
|
|
63
|
+
* @param detector Pointer to the detector.
|
|
64
|
+
* @return True if the detector is of type UNKNOWN, false otherwise.
|
|
65
|
+
*/
|
|
66
|
+
static bool classof(const AEDetector* detector)
|
|
67
|
+
{
|
|
68
|
+
return detector->getKind() == AEDetector::UNKNOWN;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @brief Pure virtual function for detecting issues within a node.
|
|
73
|
+
* @param as Reference to the abstract state.
|
|
74
|
+
* @param node Pointer to the ICFG node.
|
|
75
|
+
*/
|
|
76
|
+
virtual void detect(AbstractState& as, const ICFGNode* node) = 0;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @brief Pure virtual function to report detected bugs.
|
|
80
|
+
*/
|
|
81
|
+
virtual void reportBug() = 0;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @brief Get the kind of the detector.
|
|
85
|
+
* @return The kind of the detector.
|
|
86
|
+
*/
|
|
87
|
+
DetectorKind getKind() const
|
|
88
|
+
{
|
|
89
|
+
return kind;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
protected:
|
|
93
|
+
DetectorKind kind; ///< The kind of the detector.
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @class AEException
|
|
98
|
+
* @brief Exception class for handling errors in Abstract Execution.
|
|
99
|
+
*/
|
|
100
|
+
class AEException : public std::exception
|
|
101
|
+
{
|
|
102
|
+
public:
|
|
103
|
+
/**
|
|
104
|
+
* @brief Constructor initializes the exception with a message.
|
|
105
|
+
* @param message The error message.
|
|
106
|
+
*/
|
|
107
|
+
AEException(const std::string& message)
|
|
108
|
+
: msg_(message) {}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @brief Provides the error message.
|
|
112
|
+
* @return The error message as a C-string.
|
|
113
|
+
*/
|
|
114
|
+
virtual const char* what() const throw()
|
|
115
|
+
{
|
|
116
|
+
return msg_.c_str();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private:
|
|
120
|
+
std::string msg_; ///< The error message.
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @class BufOverflowDetector
|
|
125
|
+
* @brief Detector for identifying buffer overflow issues.
|
|
126
|
+
*/
|
|
127
|
+
class BufOverflowDetector : public AEDetector
|
|
128
|
+
{
|
|
129
|
+
friend class AbstractInterpretation;
|
|
130
|
+
public:
|
|
131
|
+
/**
|
|
132
|
+
* @brief Constructor initializes the detector kind to BUF_OVERFLOW and sets up external API buffer overflow rules.
|
|
133
|
+
*/
|
|
134
|
+
BufOverflowDetector()
|
|
135
|
+
{
|
|
136
|
+
kind = BUF_OVERFLOW;
|
|
137
|
+
initExtAPIBufOverflowCheckRules();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @brief Destructor.
|
|
142
|
+
*/
|
|
143
|
+
~BufOverflowDetector() = default;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @brief Check if the detector is of the BUF_OVERFLOW kind.
|
|
147
|
+
* @param detector Pointer to the detector.
|
|
148
|
+
* @return True if the detector is of type BUF_OVERFLOW, false otherwise.
|
|
149
|
+
*/
|
|
150
|
+
static bool classof(const AEDetector* detector)
|
|
151
|
+
{
|
|
152
|
+
return detector->getKind() == AEDetector::BUF_OVERFLOW;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @brief Updates the offset of a GEP object from its base.
|
|
157
|
+
* @param gepAddrs Address value for GEP.
|
|
158
|
+
* @param objAddrs Address value for the object.
|
|
159
|
+
* @param offset The interval value of the offset.
|
|
160
|
+
*/
|
|
161
|
+
void updateGepObjOffsetFromBase(AddressValue gepAddrs,
|
|
162
|
+
AddressValue objAddrs,
|
|
163
|
+
IntervalValue offset);
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @brief Detect buffer overflow issues within a node.
|
|
167
|
+
* @param as Reference to the abstract state.
|
|
168
|
+
* @param node Pointer to the ICFG node.
|
|
169
|
+
*/
|
|
170
|
+
void detect(AbstractState& as, const ICFGNode*);
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @brief Adds an offset to a GEP object.
|
|
174
|
+
* @param obj Pointer to the GEP object.
|
|
175
|
+
* @param offset The interval value of the offset.
|
|
176
|
+
*/
|
|
177
|
+
void addToGepObjOffsetFromBase(const GepObjVar* obj, const IntervalValue& offset)
|
|
178
|
+
{
|
|
179
|
+
gepObjOffsetFromBase[obj] = offset;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @brief Checks if a GEP object has an associated offset.
|
|
184
|
+
* @param obj Pointer to the GEP object.
|
|
185
|
+
* @return True if the GEP object has an offset, false otherwise.
|
|
186
|
+
*/
|
|
187
|
+
bool hasGepObjOffsetFromBase(const GepObjVar* obj) const
|
|
188
|
+
{
|
|
189
|
+
return gepObjOffsetFromBase.find(obj) != gepObjOffsetFromBase.end();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @brief Retrieves the offset of a GEP object from its base.
|
|
194
|
+
* @param obj Pointer to the GEP object.
|
|
195
|
+
* @return The interval value of the offset.
|
|
196
|
+
*/
|
|
197
|
+
IntervalValue getGepObjOffsetFromBase(const GepObjVar* obj) const
|
|
198
|
+
{
|
|
199
|
+
if (hasGepObjOffsetFromBase(obj))
|
|
200
|
+
return gepObjOffsetFromBase.at(obj);
|
|
201
|
+
else
|
|
202
|
+
assert(false && "GepObjVar not found in gepObjOffsetFromBase");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @brief Retrieves the access offset for a given object and GEP statement.
|
|
207
|
+
* @param as Reference to the abstract state.
|
|
208
|
+
* @param objId The ID of the object.
|
|
209
|
+
* @param gep Pointer to the GEP statement.
|
|
210
|
+
* @return The interval value of the access offset.
|
|
211
|
+
*/
|
|
212
|
+
IntervalValue getAccessOffset(AbstractState& as, NodeID objId, const GepStmt* gep);
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @brief Adds a bug to the reporter based on an exception.
|
|
216
|
+
* @param e The exception that was thrown.
|
|
217
|
+
* @param node Pointer to the ICFG node where the bug was detected.
|
|
218
|
+
*/
|
|
219
|
+
void addBugToReporter(const AEException& e, const ICFGNode* node)
|
|
220
|
+
{
|
|
221
|
+
const SVFInstruction* inst = nullptr;
|
|
222
|
+
|
|
223
|
+
// Determine the instruction associated with the ICFG node
|
|
224
|
+
if (const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(node))
|
|
225
|
+
{
|
|
226
|
+
inst = call->getCallSite(); // If the node is a call node, get the call site instruction
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
{
|
|
230
|
+
inst = node->getSVFStmts().back()->getInst(); // Otherwise, get the last instruction of the node's
|
|
231
|
+
// statements
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
GenericBug::EventStack eventStack;
|
|
235
|
+
SVFBugEvent sourceInstEvent(SVFBugEvent::EventType::SourceInst, inst);
|
|
236
|
+
eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
|
|
237
|
+
|
|
238
|
+
if (eventStack.empty())
|
|
239
|
+
{
|
|
240
|
+
return; // If the event stack is empty, return early
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
|
|
244
|
+
|
|
245
|
+
// Check if the bug at this location has already been reported
|
|
246
|
+
if (bugLoc.find(loc) != bugLoc.end())
|
|
247
|
+
{
|
|
248
|
+
return; // If the bug location is already reported, return early
|
|
249
|
+
}
|
|
250
|
+
else
|
|
251
|
+
{
|
|
252
|
+
bugLoc.insert(loc); // Otherwise, mark this location as reported
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Add the bug to the recorder with details from the event stack
|
|
256
|
+
recoder.addAbsExecBug(GenericBug::FULLBUFOVERFLOW, eventStack, 0, 0, 0, 0);
|
|
257
|
+
nodeToBugInfo[node] = e.what(); // Record the exception information for the node
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @brief Reports all detected buffer overflow bugs.
|
|
262
|
+
*/
|
|
263
|
+
void reportBug()
|
|
264
|
+
{
|
|
265
|
+
if (!nodeToBugInfo.empty())
|
|
266
|
+
{
|
|
267
|
+
std::cerr << "######################Buffer Overflow (" + std::to_string(nodeToBugInfo.size())
|
|
268
|
+
+ " found)######################\n";
|
|
269
|
+
std::cerr << "---------------------------------------------\n";
|
|
270
|
+
for (const auto& it : nodeToBugInfo)
|
|
271
|
+
{
|
|
272
|
+
std::cerr << it.second << "\n---------------------------------------------\n";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @brief Initializes external API buffer overflow check rules.
|
|
279
|
+
*/
|
|
280
|
+
void initExtAPIBufOverflowCheckRules();
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @brief Handles external API calls related to buffer overflow detection.
|
|
284
|
+
* @param as Reference to the abstract state.
|
|
285
|
+
* @param call Pointer to the call ICFG node.
|
|
286
|
+
*/
|
|
287
|
+
void detectExtAPI(AbstractState& as, const CallICFGNode *call);
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @brief Checks if memory can be safely accessed.
|
|
291
|
+
* @param as Reference to the abstract state.
|
|
292
|
+
* @param value Pointer to the SVF value.
|
|
293
|
+
* @param len The interval value representing the length of the memory access.
|
|
294
|
+
* @return True if the memory access is safe, false otherwise.
|
|
295
|
+
*/
|
|
296
|
+
bool canSafelyAccessMemory(AbstractState& as, const SVFValue *value, const IntervalValue &len);
|
|
297
|
+
|
|
298
|
+
private:
|
|
299
|
+
/**
|
|
300
|
+
* @brief Detects buffer overflow in 'strcat' function calls.
|
|
301
|
+
* @param as Reference to the abstract state.
|
|
302
|
+
* @param call Pointer to the call ICFG node.
|
|
303
|
+
* @return True if a buffer overflow is detected, false otherwise.
|
|
304
|
+
*/
|
|
305
|
+
bool detectStrcat(AbstractState& as, const CallICFGNode *call);
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @brief Detects buffer overflow in 'strcpy' function calls.
|
|
309
|
+
* @param as Reference to the abstract state.
|
|
310
|
+
* @param call Pointer to the call ICFG node.
|
|
311
|
+
* @return True if a buffer overflow is detected, false otherwise.
|
|
312
|
+
*/
|
|
313
|
+
bool detectStrcpy(AbstractState& as, const CallICFGNode *call);
|
|
314
|
+
|
|
315
|
+
private:
|
|
316
|
+
Map<const GepObjVar*, IntervalValue> gepObjOffsetFromBase; ///< Maps GEP objects to their offsets from the base.
|
|
317
|
+
Map<std::string, std::vector<std::pair<u32_t, u32_t>>> extAPIBufOverflowCheckRules; ///< Rules for checking buffer overflows in external APIs.
|
|
318
|
+
Set<std::string> bugLoc; ///< Set of locations where bugs have been reported.
|
|
319
|
+
SVFBugReport recoder; ///< Recorder for abstract execution bugs.
|
|
320
|
+
Map<const ICFGNode*, std::string> nodeToBugInfo; ///< Maps ICFG nodes to bug information.
|
|
321
|
+
};
|
|
322
|
+
}
|
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
28
28
|
// 46th International Conference on Software Engineering. (ICSE24)
|
|
29
29
|
//
|
|
30
|
-
|
|
30
|
+
#pragma once
|
|
31
|
+
#include "AE/Core/AbstractState.h"
|
|
31
32
|
#include "AE/Core/ICFGWTO.h"
|
|
33
|
+
#include "AE/Svfexe/AEDetector.h"
|
|
32
34
|
#include "Util/SVFBugReport.h"
|
|
33
35
|
#include "WPA/Andersen.h"
|
|
34
|
-
#include "AE/Core/AbstractState.h"
|
|
35
36
|
|
|
36
37
|
namespace SVF
|
|
37
38
|
{
|
|
@@ -41,12 +42,6 @@ class AEAPI;
|
|
|
41
42
|
|
|
42
43
|
template<typename T> class FILOWorkList;
|
|
43
44
|
|
|
44
|
-
enum class AEKind
|
|
45
|
-
{
|
|
46
|
-
AbstractExecution,
|
|
47
|
-
BufOverflowChecker,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
45
|
/// AEStat: Statistic for AE
|
|
51
46
|
class AEStat : public SVFStat
|
|
52
47
|
{
|
|
@@ -67,14 +62,12 @@ public:
|
|
|
67
62
|
|
|
68
63
|
void finializeStat();
|
|
69
64
|
void performStat() override;
|
|
70
|
-
void reportBug();
|
|
71
65
|
|
|
72
66
|
public:
|
|
73
67
|
AbstractInterpretation* _ae;
|
|
74
68
|
s32_t count{0};
|
|
75
69
|
std::string memory_usage;
|
|
76
70
|
std::string memUsage;
|
|
77
|
-
std::string bugStr;
|
|
78
71
|
|
|
79
72
|
|
|
80
73
|
u32_t& getFunctionTrace()
|
|
@@ -108,6 +101,7 @@ class AbstractInterpretation
|
|
|
108
101
|
{
|
|
109
102
|
friend class AEStat;
|
|
110
103
|
friend class AEAPI;
|
|
104
|
+
friend class BufOverflowDetector;
|
|
111
105
|
|
|
112
106
|
public:
|
|
113
107
|
enum ExtAPIType { UNCLASSIFIED, MEMCPY, MEMSET, STRCPY, STRCAT };
|
|
@@ -123,14 +117,15 @@ public:
|
|
|
123
117
|
/// Program entry
|
|
124
118
|
void analyse();
|
|
125
119
|
|
|
126
|
-
static
|
|
120
|
+
static AbstractInterpretation& getAEInstance()
|
|
127
121
|
{
|
|
128
|
-
|
|
122
|
+
static AbstractInterpretation instance;
|
|
123
|
+
return instance;
|
|
129
124
|
}
|
|
130
125
|
|
|
131
|
-
|
|
126
|
+
void addDetector(std::unique_ptr<AEDetector> detector)
|
|
132
127
|
{
|
|
133
|
-
|
|
128
|
+
detectors.push_back(std::move(detector));
|
|
134
129
|
}
|
|
135
130
|
|
|
136
131
|
protected:
|
|
@@ -233,13 +228,6 @@ protected:
|
|
|
233
228
|
*/
|
|
234
229
|
virtual void initExtFunMap();
|
|
235
230
|
|
|
236
|
-
/**
|
|
237
|
-
* get byte size of alloca inst
|
|
238
|
-
*
|
|
239
|
-
* @param addr Address Stmt like malloc/calloc/ALLOCA/StackAlloc
|
|
240
|
-
* @return the byte size e.g. int32_t a[10] -> return 40
|
|
241
|
-
*/
|
|
242
|
-
u32_t getAllocaInstByteSize(AbstractState& as, const AddrStmt *addr);
|
|
243
231
|
|
|
244
232
|
/**
|
|
245
233
|
* get byte size of alloca inst
|
|
@@ -259,16 +247,6 @@ protected:
|
|
|
259
247
|
*/
|
|
260
248
|
IntervalValue getStrlen(AbstractState& as, const SVF::SVFValue *strValue);
|
|
261
249
|
|
|
262
|
-
/**
|
|
263
|
-
* get memory allocation size
|
|
264
|
-
* e.g arr = new int[10]
|
|
265
|
-
* ....
|
|
266
|
-
* memset(arr, 1, 10* sizeof(int))
|
|
267
|
-
* when we trace the 'arr', we can get the alloc size [40, 40]
|
|
268
|
-
* @param value to be traced
|
|
269
|
-
* @return IntervalValue of allocation size
|
|
270
|
-
*/
|
|
271
|
-
IntervalValue traceMemoryAllocationSize(AbstractState& as, const SVFValue *value);
|
|
272
250
|
/**
|
|
273
251
|
* execute strcpy in abstract execution
|
|
274
252
|
* e.g arr = new char[10]
|
|
@@ -305,23 +283,9 @@ protected:
|
|
|
305
283
|
*/
|
|
306
284
|
virtual void handleMemset(AbstractState& as, const SVFValue* dst, IntervalValue elem, IntervalValue len);
|
|
307
285
|
|
|
308
|
-
/**
|
|
309
|
-
* if this NodeID in SVFIR is a pointer, get the pointee type
|
|
310
|
-
* e.g arr = (int*) malloc(10*sizeof(int))
|
|
311
|
-
* getPointeeType(arr) -> return int
|
|
312
|
-
* we can set arr[0]='c', arr[1]='c', arr[2]='\0'
|
|
313
|
-
* @param call callnode of memset like api
|
|
314
|
-
*/
|
|
315
|
-
const SVFType* getPointeeElement(AbstractState& as, NodeID id);
|
|
316
286
|
|
|
317
287
|
void collectCheckPoint();
|
|
318
288
|
void checkPointAllSet();
|
|
319
|
-
// helper functions for traceMemoryAllocationSize and canSafelyAccessMemory
|
|
320
|
-
void AccessMemoryViaRetNode(const CallICFGNode *callnode, SVF::FILOWorkList<const SVFValue *>& worklist, Set<const SVFValue *>& visited);
|
|
321
|
-
void AccessMemoryViaCopyStmt(const CopyStmt *copy, SVF::FILOWorkList<const SVFValue *>& worklist, Set<const SVFValue *>& visited);
|
|
322
|
-
void AccessMemoryViaLoadStmt(AbstractState& as, const LoadStmt *load, SVF::FILOWorkList<const SVFValue *>& worklist, Set<const SVFValue *>& visited);
|
|
323
|
-
void AccessMemoryViaCallArgs(const SVF::SVFArgument *arg, SVF::FILOWorkList<const SVFValue *>& worklist, Set<const SVFValue *>& visited);
|
|
324
|
-
|
|
325
289
|
|
|
326
290
|
void updateStateOnAddr(const AddrStmt *addr);
|
|
327
291
|
|
|
@@ -349,20 +313,16 @@ protected:
|
|
|
349
313
|
|
|
350
314
|
|
|
351
315
|
/// protected data members, also used in subclasses
|
|
352
|
-
SVFIR*
|
|
316
|
+
SVFIR* svfir;
|
|
353
317
|
/// Execution State, used to store the Interval Value of every SVF variable
|
|
354
|
-
AEAPI*
|
|
318
|
+
AEAPI* api{nullptr};
|
|
355
319
|
|
|
356
|
-
ICFG*
|
|
357
|
-
AEStat*
|
|
358
|
-
AEKind _kind;
|
|
320
|
+
ICFG* icfg;
|
|
321
|
+
AEStat* stat;
|
|
359
322
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
Map<const ICFGNode*, std::string> _nodeToBugInfo;
|
|
364
|
-
Map<const SVFFunction*, ICFGWTO*> _funcToWTO;
|
|
365
|
-
Set<const SVFFunction*> _recursiveFuns;
|
|
323
|
+
std::vector<const CallICFGNode*> callSiteStack;
|
|
324
|
+
Map<const SVFFunction*, ICFGWTO*> funcToWTO;
|
|
325
|
+
Set<const SVFFunction*> recursiveFuns;
|
|
366
326
|
|
|
367
327
|
private:
|
|
368
328
|
// helper functions in handleCallSite
|
|
@@ -379,29 +339,33 @@ protected:
|
|
|
379
339
|
|
|
380
340
|
AbstractState& getAbsStateFromTrace(const ICFGNode* node)
|
|
381
341
|
{
|
|
382
|
-
const ICFGNode* repNode =
|
|
383
|
-
if (
|
|
342
|
+
const ICFGNode* repNode = icfg->getRepNode(node);
|
|
343
|
+
if (abstractTrace.count(repNode) == 0)
|
|
384
344
|
{
|
|
385
345
|
assert(0 && "No preAbsTrace for this node");
|
|
386
346
|
}
|
|
387
347
|
else
|
|
388
348
|
{
|
|
389
|
-
return
|
|
349
|
+
return abstractTrace[repNode];
|
|
390
350
|
}
|
|
391
351
|
}
|
|
392
352
|
|
|
393
353
|
bool hasAbsStateFromTrace(const ICFGNode* node)
|
|
394
354
|
{
|
|
395
|
-
const ICFGNode* repNode =
|
|
396
|
-
return
|
|
355
|
+
const ICFGNode* repNode = icfg->getRepNode(node);
|
|
356
|
+
return abstractTrace.count(repNode) != 0;
|
|
397
357
|
}
|
|
398
358
|
|
|
399
359
|
protected:
|
|
400
360
|
// there data should be shared with subclasses
|
|
401
|
-
Map<std::string, std::function<void(const CallSite &)>>
|
|
402
|
-
Set<const CallICFGNode*>
|
|
403
|
-
Set<std::string>
|
|
404
|
-
Map<const ICFGNode*, AbstractState>
|
|
405
|
-
|
|
361
|
+
Map<std::string, std::function<void(const CallSite &)>> func_map;
|
|
362
|
+
Set<const CallICFGNode*> checkpoints;
|
|
363
|
+
Set<std::string> checkpoint_names;
|
|
364
|
+
Map<const ICFGNode*, AbstractState>
|
|
365
|
+
abstractTrace; // abstract states immediately after nodes
|
|
366
|
+
std::string moduleName;
|
|
367
|
+
|
|
368
|
+
std::vector<std::unique_ptr<AEDetector>> detectors;
|
|
369
|
+
|
|
406
370
|
};
|
|
407
371
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -198,12 +198,21 @@ public:
|
|
|
198
198
|
//@{
|
|
199
199
|
ICFGNode* getICFGNode(const SVFInstruction* inst);
|
|
200
200
|
|
|
201
|
+
/// Whether has the ICFGNode
|
|
202
|
+
bool hasICFGNode(const SVFInstruction* inst);
|
|
203
|
+
|
|
201
204
|
CallICFGNode* getCallICFGNode(const SVFInstruction* inst);
|
|
202
205
|
|
|
206
|
+
CallICFGNode* addCallICFGNode(const SVFInstruction* inst);
|
|
207
|
+
|
|
203
208
|
RetICFGNode* getRetICFGNode(const SVFInstruction* inst);
|
|
204
209
|
|
|
210
|
+
RetICFGNode* addRetICFGNode(const SVFInstruction* inst);
|
|
211
|
+
|
|
205
212
|
IntraICFGNode* getIntraICFGNode(const SVFInstruction* inst);
|
|
206
213
|
|
|
214
|
+
IntraICFGNode* addIntraICFGNode(const SVFInstruction* inst);
|
|
215
|
+
|
|
207
216
|
FunEntryICFGNode* getFunEntryICFGNode(const SVFFunction* fun);
|
|
208
217
|
|
|
209
218
|
FunExitICFGNode* getFunExitICFGNode(const SVFFunction* fun);
|
|
@@ -470,9 +470,9 @@ public:
|
|
|
470
470
|
}
|
|
471
471
|
//@}
|
|
472
472
|
/// Whether this instruction has SVFIR Edge
|
|
473
|
-
bool hasSVFStmtList(const
|
|
473
|
+
bool hasSVFStmtList(const ICFGNode* icfgNode);
|
|
474
474
|
/// Given an instruction, get all its the PAGEdge (statement) in sequence
|
|
475
|
-
SVFStmtList& getPAGEdgesFromInst(const
|
|
475
|
+
SVFStmtList& getPAGEdgesFromInst(const ICFGNode* node);
|
|
476
476
|
|
|
477
477
|
/// getModRefInfo APIs
|
|
478
478
|
//@{
|
|
@@ -341,8 +341,7 @@ public:
|
|
|
341
341
|
NodeID parentTid = tct->getParentThread(tid);
|
|
342
342
|
const CxtThread& parentct = tct->getTCTNode(parentTid)->getCxtThread();
|
|
343
343
|
const SVFFunction* parentRoutine = tct->getStartRoutineOfCxtThread(parentct);
|
|
344
|
-
|
|
345
|
-
return tct->getICFGNode(inst);
|
|
344
|
+
return parentRoutine->getExitBB()->back();
|
|
346
345
|
}
|
|
347
346
|
|
|
348
347
|
/// Get loop for join site
|
|
@@ -62,23 +62,30 @@ private:
|
|
|
62
62
|
///@{
|
|
63
63
|
void processFunEntry(const Function* fun, WorkList& worklist);
|
|
64
64
|
|
|
65
|
+
void processNoPrecessorBasicBlocks(const Function* fun, WorkList& worklist);
|
|
66
|
+
|
|
65
67
|
void processFunBody(WorkList& worklist);
|
|
66
68
|
|
|
67
69
|
void processFunExit(const Function* fun);
|
|
68
70
|
//@}
|
|
69
71
|
|
|
72
|
+
void checkICFGNodesVisited(const Function* fun);
|
|
73
|
+
|
|
70
74
|
void connectGlobalToProgEntry(SVFModule* svfModule);
|
|
71
75
|
|
|
72
76
|
/// Add/Get an inter block ICFGNode
|
|
73
|
-
InterICFGNode*
|
|
77
|
+
InterICFGNode* addInterBlockICFGNode(const SVFInstruction* inst);
|
|
74
78
|
|
|
75
79
|
/// Add/Get a basic block ICFGNode
|
|
76
|
-
inline ICFGNode*
|
|
80
|
+
inline ICFGNode* addBlockICFGNode(const SVFInstruction* inst)
|
|
77
81
|
{
|
|
82
|
+
ICFGNode* node;
|
|
78
83
|
if(SVFUtil::isNonInstricCallSite(inst))
|
|
79
|
-
|
|
84
|
+
node = addInterBlockICFGNode(inst);
|
|
80
85
|
else
|
|
81
|
-
|
|
86
|
+
node = addIntraBlockICFGNode(inst);
|
|
87
|
+
const_cast<SVFBasicBlock*>(inst->getParent())->addICFGNode(node);
|
|
88
|
+
return node;
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
/// Create edges between ICFG nodes across functions
|
|
@@ -96,10 +103,13 @@ private:
|
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
/// Add and get IntraBlock ICFGNode
|
|
99
|
-
IntraICFGNode*
|
|
106
|
+
IntraICFGNode* addIntraBlockICFGNode(const SVFInstruction* inst)
|
|
100
107
|
{
|
|
101
|
-
return icfg->
|
|
108
|
+
return icfg->addIntraICFGNode(inst);
|
|
102
109
|
}
|
|
110
|
+
|
|
111
|
+
private:
|
|
112
|
+
BBSet visited;
|
|
103
113
|
};
|
|
104
114
|
|
|
105
115
|
} // End namespace SVF
|
|
@@ -303,6 +303,17 @@ void getNextInsts(const Instruction* curInst,
|
|
|
303
303
|
void getPrevInsts(const Instruction* curInst,
|
|
304
304
|
std::vector<const Instruction*>& instList);
|
|
305
305
|
|
|
306
|
+
/// Basic block does not have predecessors
|
|
307
|
+
/// map-1.cpp.bc
|
|
308
|
+
/// try.cont: ; No predecessors!
|
|
309
|
+
/// call void @llvm.trap()
|
|
310
|
+
/// unreachable
|
|
311
|
+
inline bool isNoPrecessorBasicBlock(const BasicBlock* bb)
|
|
312
|
+
{
|
|
313
|
+
return bb != &bb->getParent()->getEntryBlock() &&
|
|
314
|
+
pred_empty(bb);
|
|
315
|
+
}
|
|
316
|
+
|
|
306
317
|
/// Get num of BB's predecessors
|
|
307
318
|
u32_t getBBPredecessorNum(const BasicBlock* BB);
|
|
308
319
|
|
|
@@ -450,9 +450,9 @@ protected:
|
|
|
450
450
|
/// Add Store edge
|
|
451
451
|
inline void addStoreEdge(NodeID src, NodeID dst)
|
|
452
452
|
{
|
|
453
|
-
|
|
453
|
+
ICFGNode* node;
|
|
454
454
|
if (const SVFInstruction* inst = SVFUtil::dyn_cast<SVFInstruction>(curVal))
|
|
455
|
-
node = pag->getICFG()->
|
|
455
|
+
node = pag->getICFG()->getICFGNode(inst);
|
|
456
456
|
else
|
|
457
457
|
node = nullptr;
|
|
458
458
|
if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
|
|
@@ -658,7 +658,7 @@ private:
|
|
|
658
658
|
/// Add Load edge
|
|
659
659
|
LoadStmt* addLoadStmt(NodeID src, NodeID dst);
|
|
660
660
|
/// Add Store edge
|
|
661
|
-
StoreStmt* addStoreStmt(NodeID src, NodeID dst, const
|
|
661
|
+
StoreStmt* addStoreStmt(NodeID src, NodeID dst, const ICFGNode* val);
|
|
662
662
|
/// Add Call edge
|
|
663
663
|
CallPE* addCallPE(NodeID src, NodeID dst, const CallICFGNode* cs,
|
|
664
664
|
const FunEntryICFGNode* entry);
|
|
@@ -524,6 +524,8 @@ public:
|
|
|
524
524
|
}
|
|
525
525
|
};
|
|
526
526
|
|
|
527
|
+
class ICFGNode;
|
|
528
|
+
|
|
527
529
|
class SVFBasicBlock : public SVFValue
|
|
528
530
|
{
|
|
529
531
|
friend class LLVMModuleSet;
|
|
@@ -531,21 +533,26 @@ class SVFBasicBlock : public SVFValue
|
|
|
531
533
|
friend class SVFIRReader;
|
|
532
534
|
friend class SVFIRBuilder;
|
|
533
535
|
friend class SVFFunction;
|
|
536
|
+
friend class ICFGBuilder;
|
|
537
|
+
friend class ICFG;
|
|
534
538
|
|
|
535
539
|
public:
|
|
536
|
-
typedef std::vector<const
|
|
540
|
+
typedef std::vector<const ICFGNode*>::const_iterator const_iterator;
|
|
537
541
|
|
|
538
542
|
private:
|
|
539
|
-
std::vector<const
|
|
543
|
+
std::vector<const ICFGNode*> allICFGNodes; ///< all ICFGNodes in this BasicBlock
|
|
540
544
|
std::vector<const SVFBasicBlock*> succBBs; ///< all successor BasicBlocks of this BasicBlock
|
|
541
545
|
std::vector<const SVFBasicBlock*> predBBs; ///< all predecessor BasicBlocks of this BasicBlock
|
|
542
546
|
const SVFFunction* fun; /// Function where this BasicBlock is
|
|
543
547
|
|
|
544
548
|
protected:
|
|
545
549
|
///@{ attributes to be set only through Module builders e.g., LLVMModule
|
|
546
|
-
|
|
550
|
+
|
|
551
|
+
inline void addICFGNode(const ICFGNode* icfgNode)
|
|
547
552
|
{
|
|
548
|
-
|
|
553
|
+
assert(std::find(getICFGNodeList().begin(), getICFGNodeList().end(),
|
|
554
|
+
icfgNode) == getICFGNodeList().end() && "duplicated icfgnode");
|
|
555
|
+
allICFGNodes.push_back(icfgNode);
|
|
549
556
|
}
|
|
550
557
|
|
|
551
558
|
inline void addSuccBasicBlock(const SVFBasicBlock* succ)
|
|
@@ -570,19 +577,19 @@ public:
|
|
|
570
577
|
return node->getKind() == SVFBB;
|
|
571
578
|
}
|
|
572
579
|
|
|
573
|
-
inline const std::vector<const
|
|
580
|
+
inline const std::vector<const ICFGNode*>& getICFGNodeList() const
|
|
574
581
|
{
|
|
575
|
-
return
|
|
582
|
+
return allICFGNodes;
|
|
576
583
|
}
|
|
577
584
|
|
|
578
585
|
inline const_iterator begin() const
|
|
579
586
|
{
|
|
580
|
-
return
|
|
587
|
+
return allICFGNodes.begin();
|
|
581
588
|
}
|
|
582
589
|
|
|
583
590
|
inline const_iterator end() const
|
|
584
591
|
{
|
|
585
|
-
return
|
|
592
|
+
return allICFGNodes.end();
|
|
586
593
|
}
|
|
587
594
|
|
|
588
595
|
inline const SVFFunction* getParent() const
|
|
@@ -595,20 +602,18 @@ public:
|
|
|
595
602
|
return fun;
|
|
596
603
|
}
|
|
597
604
|
|
|
598
|
-
inline const
|
|
605
|
+
inline const ICFGNode* front() const
|
|
599
606
|
{
|
|
600
|
-
|
|
607
|
+
assert(!allICFGNodes.empty() && "bb empty?");
|
|
608
|
+
return allICFGNodes.front();
|
|
601
609
|
}
|
|
602
610
|
|
|
603
|
-
inline const
|
|
611
|
+
inline const ICFGNode* back() const
|
|
604
612
|
{
|
|
605
|
-
|
|
613
|
+
assert(!allICFGNodes.empty() && "bb empty?");
|
|
614
|
+
return allICFGNodes.back();
|
|
606
615
|
}
|
|
607
616
|
|
|
608
|
-
/// Returns the terminator instruction if the block is well formed or null
|
|
609
|
-
/// if the block is not well formed.
|
|
610
|
-
const SVFInstruction* getTerminator() const;
|
|
611
|
-
|
|
612
617
|
inline const std::vector<const SVFBasicBlock*>& getSuccessors() const
|
|
613
618
|
{
|
|
614
619
|
return succBBs;
|
|
@@ -168,6 +168,8 @@ void dumpPointsToList(const PointsToList& ptl);
|
|
|
168
168
|
|
|
169
169
|
/// Return true if it is an llvm intrinsic instruction
|
|
170
170
|
bool isIntrinsicInst(const SVFInstruction* inst);
|
|
171
|
+
bool isIntrinsicInst(const ICFGNode* inst);
|
|
172
|
+
|
|
171
173
|
//@}
|
|
172
174
|
|
|
173
175
|
/// Whether an instruction is a call or invoke instruction
|
|
@@ -184,6 +186,10 @@ inline bool isCallSite(const SVFValue* val)
|
|
|
184
186
|
return false;
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
bool isCallSite(const ICFGNode* inst);
|
|
190
|
+
|
|
191
|
+
bool isRetInstNode(const ICFGNode* node);
|
|
192
|
+
|
|
187
193
|
/// Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls
|
|
188
194
|
inline bool isNonInstricCallSite(const SVFInstruction* inst)
|
|
189
195
|
{
|
|
@@ -192,6 +198,14 @@ inline bool isNonInstricCallSite(const SVFInstruction* inst)
|
|
|
192
198
|
return isCallSite(inst);
|
|
193
199
|
}
|
|
194
200
|
|
|
201
|
+
/// Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls
|
|
202
|
+
inline bool isNonInstricCallSite(const ICFGNode* inst)
|
|
203
|
+
{
|
|
204
|
+
if(isIntrinsicInst(inst))
|
|
205
|
+
return false;
|
|
206
|
+
return isCallSite(inst);
|
|
207
|
+
}
|
|
208
|
+
|
|
195
209
|
/// Return LLVM callsite given an instruction
|
|
196
210
|
inline CallSite getSVFCallSite(const SVFInstruction* inst)
|
|
197
211
|
{
|
|
@@ -250,6 +264,8 @@ inline const SVFFunction* getCallee(const SVFInstruction *inst)
|
|
|
250
264
|
CallSite cs(inst);
|
|
251
265
|
return getCallee(cs);
|
|
252
266
|
}
|
|
267
|
+
|
|
268
|
+
const SVFFunction* getCallee(const ICFGNode *inst);
|
|
253
269
|
//@}
|
|
254
270
|
|
|
255
271
|
/// Given a map mapping points-to sets to a count, adds from into to.
|
|
@@ -402,27 +418,20 @@ inline bool isArgOfUncalledFunction(const SVFValue* svfval)
|
|
|
402
418
|
|
|
403
419
|
/// Return thread fork function
|
|
404
420
|
//@{
|
|
405
|
-
inline const SVFValue* getForkedFun(const CallSite cs)
|
|
406
|
-
{
|
|
407
|
-
return ThreadAPI::getThreadAPI()->getForkedFun(cs.getInstruction());
|
|
408
|
-
}
|
|
409
421
|
inline const SVFValue* getForkedFun(const SVFInstruction *inst)
|
|
410
422
|
{
|
|
411
423
|
return ThreadAPI::getThreadAPI()->getForkedFun(inst);
|
|
412
424
|
}
|
|
413
425
|
//@}
|
|
414
426
|
|
|
415
|
-
/// This function servers a allocation wrapper detector
|
|
416
|
-
inline bool isAnAllocationWraper(const SVFInstruction*)
|
|
417
|
-
{
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
427
|
|
|
421
428
|
inline bool isExtCall(const CallSite cs)
|
|
422
429
|
{
|
|
423
430
|
return isExtCall(getCallee(cs));
|
|
424
431
|
}
|
|
425
432
|
|
|
433
|
+
bool isExtCall(const ICFGNode* node);
|
|
434
|
+
|
|
426
435
|
inline bool isExtCall(const SVFInstruction *inst)
|
|
427
436
|
{
|
|
428
437
|
return isExtCall(getCallee(inst));
|
|
@@ -451,10 +460,7 @@ inline bool isHeapAllocExtCallViaRet(const SVFInstruction *inst)
|
|
|
451
460
|
return isPtrTy && isHeapAllocExtFunViaRet(getCallee(inst));
|
|
452
461
|
}
|
|
453
462
|
|
|
454
|
-
|
|
455
|
-
{
|
|
456
|
-
return isHeapAllocExtCallViaRet(cs) || isHeapAllocExtCallViaArg(cs);
|
|
457
|
-
}
|
|
463
|
+
bool isHeapAllocExtCall(const ICFGNode* cs);
|
|
458
464
|
|
|
459
465
|
inline bool isHeapAllocExtCall(const SVFInstruction *inst)
|
|
460
466
|
{
|
|
@@ -477,10 +483,6 @@ inline bool isReallocExtCall(const CallSite cs)
|
|
|
477
483
|
|
|
478
484
|
/// Return true if this is a thread creation call
|
|
479
485
|
///@{
|
|
480
|
-
inline bool isThreadForkCall(const CallSite cs)
|
|
481
|
-
{
|
|
482
|
-
return ThreadAPI::getThreadAPI()->isTDFork(cs.getInstruction());
|
|
483
|
-
}
|
|
484
486
|
inline bool isThreadForkCall(const SVFInstruction *inst)
|
|
485
487
|
{
|
|
486
488
|
return ThreadAPI::getThreadAPI()->isTDFork(inst);
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
//===- BufOverflowChecker.cpp -- BufOVerflowChecker Client for 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/12.
|
|
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
|
-
|
|
31
|
-
#include "AE/Svfexe/AbstractInterpretation.h"
|
|
32
|
-
|
|
33
|
-
namespace SVF
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
struct BufOverflowException: public std::exception
|
|
37
|
-
{
|
|
38
|
-
public:
|
|
39
|
-
BufOverflowException(std::string msg, u32_t allocLb,
|
|
40
|
-
u32_t allocUb, u32_t accessLb, u32_t accessUb, const SVFValue* allocVal) :
|
|
41
|
-
_msg(msg), _allocLb(allocLb), _allocUb(allocUb),
|
|
42
|
-
_accessLb(accessLb), _accessUb(accessUb), _allocVar(allocVal)
|
|
43
|
-
{
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
u32_t getAllocLb() const
|
|
47
|
-
{
|
|
48
|
-
return _allocLb;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
void setAllocLb(u32_t allocLb)
|
|
52
|
-
{
|
|
53
|
-
_allocLb = allocLb;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
u32_t getAllocUb() const
|
|
57
|
-
{
|
|
58
|
-
return _allocUb;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
void setAllocUb(u32_t allocUb)
|
|
62
|
-
{
|
|
63
|
-
_allocUb = allocUb;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
u32_t getAccessLb() const
|
|
67
|
-
{
|
|
68
|
-
return _accessLb;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
void setAccessLb(u32_t accessLb)
|
|
72
|
-
{
|
|
73
|
-
_accessLb = accessLb;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
u32_t getAccessUb() const
|
|
77
|
-
{
|
|
78
|
-
return _accessUb;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
void setAccessUb(u32_t accessUb)
|
|
82
|
-
{
|
|
83
|
-
_accessUb = accessUb;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const SVFValue* getAllocVar() const
|
|
87
|
-
{
|
|
88
|
-
return _allocVar;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const char* what() const noexcept override
|
|
92
|
-
{
|
|
93
|
-
return _msg.c_str();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
protected:
|
|
98
|
-
std::string _msg;
|
|
99
|
-
u32_t _allocLb, _allocUb, _accessLb, _accessUb;
|
|
100
|
-
const SVFValue* _allocVar;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
class BufOverflowChecker: public AbstractInterpretation
|
|
104
|
-
{
|
|
105
|
-
public:
|
|
106
|
-
BufOverflowChecker() : AbstractInterpretation()
|
|
107
|
-
{
|
|
108
|
-
initExtFunMap();
|
|
109
|
-
_kind = AEKind::BufOverflowChecker;
|
|
110
|
-
initExtAPIBufOverflowCheckRules();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static bool classof(const AbstractInterpretation* ae)
|
|
114
|
-
{
|
|
115
|
-
return ae->getKind() == AEKind::BufOverflowChecker;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
protected:
|
|
119
|
-
/**
|
|
120
|
-
* the map of external function to its API type
|
|
121
|
-
*
|
|
122
|
-
* it initialize the ext apis about buffer overflow checking
|
|
123
|
-
*/
|
|
124
|
-
virtual void initExtFunMap() override;
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* the map of ext apis of buffer overflow checking rules
|
|
128
|
-
*
|
|
129
|
-
* it initialize the rules of extapis about buffer overflow checking
|
|
130
|
-
* e.g. memcpy(dst, src, sz) -> we check allocSize(dst)>=sz and allocSize(src)>=sz
|
|
131
|
-
*/
|
|
132
|
-
void initExtAPIBufOverflowCheckRules();
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* handle external function call regarding buffer overflow checking
|
|
136
|
-
* e.g. memcpy(dst, src, sz) -> we check allocSize(dst)>=sz and allocSize(src)>=sz
|
|
137
|
-
*
|
|
138
|
-
* @param call call node whose callee is external function
|
|
139
|
-
*/
|
|
140
|
-
void handleExtAPI(const CallICFGNode *call) override;
|
|
141
|
-
/**
|
|
142
|
-
* detect buffer overflow from strcpy like apis
|
|
143
|
-
* e.g. strcpy(dst, src), if dst is shorter than src, we will throw buffer overflow
|
|
144
|
-
*
|
|
145
|
-
* @param call call node whose callee is strcpy-like external function
|
|
146
|
-
* @return true if the buffer overflow is detected
|
|
147
|
-
*/
|
|
148
|
-
bool detectStrcpy(const CallICFGNode *call);
|
|
149
|
-
/**
|
|
150
|
-
* detect buffer overflow from strcat like apis
|
|
151
|
-
* e.g. strcat(dst, src), if dst is shorter than src, we will throw buffer overflow
|
|
152
|
-
*
|
|
153
|
-
* @param call call node whose callee is strcpy-like external function
|
|
154
|
-
* @return true if the buffer overflow is detected
|
|
155
|
-
*/
|
|
156
|
-
bool detectStrcat(const CallICFGNode *call);
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* detect buffer overflow by giving a var and a length
|
|
160
|
-
* e.g. int x[10]; x[10] = 1;
|
|
161
|
-
* we call canSafelyAccessMemory(x, 11 * sizeof(int));
|
|
162
|
-
*
|
|
163
|
-
* @param value the value of the buffer overflow checkpoint
|
|
164
|
-
* @param len the length of the buffer overflow checkpoint
|
|
165
|
-
* @return true if the buffer overflow is detected
|
|
166
|
-
*/
|
|
167
|
-
bool canSafelyAccessMemory(const SVFValue *value, const IntervalValue &len, const ICFGNode *curNode);
|
|
168
|
-
|
|
169
|
-
private:
|
|
170
|
-
/**
|
|
171
|
-
* handle SVF statement regarding buffer overflow checking
|
|
172
|
-
*
|
|
173
|
-
* @param stmt SVF statement
|
|
174
|
-
*/
|
|
175
|
-
virtual void handleSVFStatement(const SVFStmt *stmt) override;
|
|
176
|
-
|
|
177
|
-
// TODO: will delete later
|
|
178
|
-
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto) override
|
|
179
|
-
{
|
|
180
|
-
AbstractInterpretation::handleSingletonWTO(icfgSingletonWto);
|
|
181
|
-
const ICFGNode* repNode = _icfg->getRepNode(icfgSingletonWto->getICFGNode());
|
|
182
|
-
if (_abstractTrace.count(repNode) == 0)
|
|
183
|
-
{
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const std::vector<const ICFGNode*>& worklist_vec = _icfg->getSubNodes(icfgSingletonWto->getICFGNode());
|
|
187
|
-
|
|
188
|
-
for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
|
|
189
|
-
{
|
|
190
|
-
const ICFGNode* curNode = *it;
|
|
191
|
-
detectBufOverflow(curNode);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* check buffer overflow at ICFGNode which is a checkpoint
|
|
197
|
-
*
|
|
198
|
-
* @param node ICFGNode
|
|
199
|
-
* @return true if the buffer overflow is detected
|
|
200
|
-
*/
|
|
201
|
-
bool detectBufOverflow(const ICFGNode *node);
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* add buffer overflow bug to recoder
|
|
205
|
-
*
|
|
206
|
-
* @param e the exception that is thrown by BufOverflowChecker
|
|
207
|
-
* @param node ICFGNode that causes the exception
|
|
208
|
-
*/
|
|
209
|
-
void addBugToRecoder(const BufOverflowException& e, const ICFGNode* node);
|
|
210
|
-
|
|
211
|
-
private:
|
|
212
|
-
Map<NodeID, const GepStmt*> _addrToGep;
|
|
213
|
-
Map<std::string, std::vector<std::pair<u32_t, u32_t>>> _extAPIBufOverflowCheckRules;
|
|
214
|
-
|
|
215
|
-
};
|
|
216
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
//===- ICFGSimplification.h -- Simplify ICFG----------------------------------//
|
|
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/2/25.
|
|
26
|
-
//
|
|
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
|
-
#include "Graphs/ICFG.h"
|
|
31
|
-
|
|
32
|
-
namespace SVF
|
|
33
|
-
{
|
|
34
|
-
|
|
35
|
-
class ICFGSimplification
|
|
36
|
-
{
|
|
37
|
-
public:
|
|
38
|
-
ICFGSimplification() = default;
|
|
39
|
-
|
|
40
|
-
virtual ~ICFGSimplification() = default;
|
|
41
|
-
|
|
42
|
-
static void mergeAdjacentNodes(ICFG* icfg);
|
|
43
|
-
};
|
|
44
|
-
}
|