svf-tools 1.0.987 → 1.0.989
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/package.json +1 -1
- package/svf/include/AE/Svfexe/AEDetector.h +15 -2
- package/svf/include/AE/Svfexe/AbsExtAPI.h +147 -0
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +25 -92
- package/svf/include/SVFIR/SVFValue.h +0 -11
- package/svf/include/Util/ExtAPI.h +10 -0
- package/svf/include/Util/SVFUtil.h +1 -7
- package/svf/lib/AE/Svfexe/AEDetector.cpp +108 -28
- package/svf/lib/AE/Svfexe/AbsExtAPI.cpp +765 -0
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +24 -797
- package/svf/lib/SVFIR/SVFFileSystem.cpp +0 -2
- package/svf/lib/Util/ExtAPI.cpp +33 -10
- package/svf/lib/Util/SVFUtil.cpp +0 -15
- package/svf-llvm/include/SVF-LLVM/LLVMModule.h +1 -58
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +10 -19
- package/svf-llvm/lib/CHGBuilder.cpp +2 -2
- package/svf-llvm/lib/LLVMModule.cpp +216 -230
- package/svf-llvm/lib/LLVMUtil.cpp +32 -228
- package/svf-llvm/lib/ObjTypeInference.cpp +2 -2
- package/svf-llvm/lib/SVFIRBuilder.cpp +0 -1
- package/svf-llvm/lib/SymbolTableBuilder.cpp +5 -6
- package/svf-llvm/lib/extapi.c +0 -1
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
//
|
|
27
27
|
|
|
28
28
|
#include <AE/Svfexe/AEDetector.h>
|
|
29
|
+
#include <AE/Svfexe/AbsExtAPI.h>
|
|
29
30
|
#include <AE/Svfexe/AbstractInterpretation.h>
|
|
30
31
|
|
|
31
32
|
using namespace SVF;
|
|
@@ -101,6 +102,85 @@ void BufOverflowDetector::detect(AbstractState& as, const ICFGNode* node)
|
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @brief Handles stub functions within the ICFG node.
|
|
108
|
+
*
|
|
109
|
+
* This function is a placeholder for handling stub functions within the ICFG node.
|
|
110
|
+
*
|
|
111
|
+
* @param node Pointer to the ICFG node.
|
|
112
|
+
*/
|
|
113
|
+
void BufOverflowDetector::handleStubFunctions(const SVF::CallICFGNode* callNode)
|
|
114
|
+
{
|
|
115
|
+
// get function name
|
|
116
|
+
SVFIR* svfir = PAG::getPAG();
|
|
117
|
+
std::string funcName = callNode->getCalledFunction()->getName();
|
|
118
|
+
if (funcName == "SAFE_BUFACCESS")
|
|
119
|
+
{
|
|
120
|
+
// void SAFE_BUFACCESS(void* data, int size);
|
|
121
|
+
AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
|
|
122
|
+
if (callNode->arg_size() < 2)
|
|
123
|
+
return;
|
|
124
|
+
AbstractState& as =
|
|
125
|
+
AbstractInterpretation::getAEInstance().getAbsStateFromTrace(
|
|
126
|
+
callNode);
|
|
127
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
128
|
+
IntervalValue val = as[size_id].getInterval();
|
|
129
|
+
if (val.isBottom())
|
|
130
|
+
{
|
|
131
|
+
val = IntervalValue(0);
|
|
132
|
+
assert(false && "SAFE_BUFACCESS size is bottom");
|
|
133
|
+
}
|
|
134
|
+
const SVFVar* arg0Val =
|
|
135
|
+
AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(
|
|
136
|
+
callNode->getArgument(0));
|
|
137
|
+
bool isSafe = canSafelyAccessMemory(as, arg0Val, val);
|
|
138
|
+
if (isSafe)
|
|
139
|
+
{
|
|
140
|
+
std::cout << "safe buffer access success: " << callNode->toString()
|
|
141
|
+
<< std::endl;
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
else
|
|
145
|
+
{
|
|
146
|
+
std::string err_msg = "this SAFE_BUFACCESS should be a safe access but detected buffer overflow. Pos: ";
|
|
147
|
+
err_msg += callNode->getSourceLoc();
|
|
148
|
+
std::cerr << err_msg << std::endl;
|
|
149
|
+
assert(false);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (funcName == "UNSAFE_BUFACCESS")
|
|
153
|
+
{
|
|
154
|
+
// handle other stub functions
|
|
155
|
+
//void UNSAFE_BUFACCESS(void* data, int size);
|
|
156
|
+
AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
|
|
157
|
+
if (callNode->arg_size() < 2) return;
|
|
158
|
+
AbstractState&as = AbstractInterpretation::getAEInstance().getAbsStateFromTrace(callNode);
|
|
159
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
160
|
+
IntervalValue val = as[size_id].getInterval();
|
|
161
|
+
if (val.isBottom())
|
|
162
|
+
{
|
|
163
|
+
assert(false && "UNSAFE_BUFACCESS size is bottom");
|
|
164
|
+
}
|
|
165
|
+
const SVFVar* arg0Val =
|
|
166
|
+
AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(
|
|
167
|
+
callNode->getArgument(0));
|
|
168
|
+
bool isSafe = canSafelyAccessMemory(as, arg0Val, val);
|
|
169
|
+
if (!isSafe)
|
|
170
|
+
{
|
|
171
|
+
std::cout << "detect buffer overflow success: " << callNode->toString() << std::endl;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
else
|
|
175
|
+
{
|
|
176
|
+
std::string err_msg = "this UNSAFE_BUFACCESS should be a buffer overflow but not detected. Pos: ";
|
|
177
|
+
err_msg += callNode->getSourceLoc();
|
|
178
|
+
std::cerr << err_msg << std::endl;
|
|
179
|
+
assert(false);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
104
184
|
/**
|
|
105
185
|
* @brief Initializes external API buffer overflow check rules.
|
|
106
186
|
*
|
|
@@ -147,23 +227,23 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
147
227
|
SVFIR* svfir = PAG::getPAG();
|
|
148
228
|
assert(call->getCalledFunction() && "SVFFunction* is nullptr");
|
|
149
229
|
|
|
150
|
-
|
|
230
|
+
AbsExtAPI::ExtAPIType extType = AbsExtAPI::UNCLASSIFIED;
|
|
151
231
|
|
|
152
232
|
// Determine the type of external memory API
|
|
153
|
-
for (const std::string &annotation : call->getCalledFunction()
|
|
233
|
+
for (const std::string &annotation : ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
|
|
154
234
|
{
|
|
155
235
|
if (annotation.find("MEMCPY") != std::string::npos)
|
|
156
|
-
extType =
|
|
236
|
+
extType = AbsExtAPI::MEMCPY;
|
|
157
237
|
if (annotation.find("MEMSET") != std::string::npos)
|
|
158
|
-
extType =
|
|
238
|
+
extType = AbsExtAPI::MEMSET;
|
|
159
239
|
if (annotation.find("STRCPY") != std::string::npos)
|
|
160
|
-
extType =
|
|
240
|
+
extType = AbsExtAPI::STRCPY;
|
|
161
241
|
if (annotation.find("STRCAT") != std::string::npos)
|
|
162
|
-
extType =
|
|
242
|
+
extType = AbsExtAPI::STRCAT;
|
|
163
243
|
}
|
|
164
244
|
|
|
165
245
|
// Apply buffer overflow checks based on the determined API type
|
|
166
|
-
if (extType ==
|
|
246
|
+
if (extType == AbsExtAPI::MEMCPY)
|
|
167
247
|
{
|
|
168
248
|
if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
|
|
169
249
|
{
|
|
@@ -175,14 +255,15 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
175
255
|
for (auto arg : args)
|
|
176
256
|
{
|
|
177
257
|
IntervalValue offset = as[svfir->getValueNode(call->getArgument(arg.second))].getInterval() - IntervalValue(1);
|
|
178
|
-
|
|
258
|
+
const SVFVar* argVar = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(arg.first));
|
|
259
|
+
if (!canSafelyAccessMemory(as, argVar, offset))
|
|
179
260
|
{
|
|
180
261
|
AEException bug(call->toString());
|
|
181
262
|
addBugToReporter(bug, call);
|
|
182
263
|
}
|
|
183
264
|
}
|
|
184
265
|
}
|
|
185
|
-
else if (extType ==
|
|
266
|
+
else if (extType == AbsExtAPI::MEMSET)
|
|
186
267
|
{
|
|
187
268
|
if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
|
|
188
269
|
{
|
|
@@ -194,14 +275,15 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
194
275
|
for (auto arg : args)
|
|
195
276
|
{
|
|
196
277
|
IntervalValue offset = as[svfir->getValueNode(call->getArgument(arg.second))].getInterval() - IntervalValue(1);
|
|
197
|
-
|
|
278
|
+
const SVFVar* argVar = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(arg.first));
|
|
279
|
+
if (!canSafelyAccessMemory(as, argVar, offset))
|
|
198
280
|
{
|
|
199
281
|
AEException bug(call->toString());
|
|
200
282
|
addBugToReporter(bug, call);
|
|
201
283
|
}
|
|
202
284
|
}
|
|
203
285
|
}
|
|
204
|
-
else if (extType ==
|
|
286
|
+
else if (extType == AbsExtAPI::STRCPY)
|
|
205
287
|
{
|
|
206
288
|
if (!detectStrcpy(as, call))
|
|
207
289
|
{
|
|
@@ -209,7 +291,7 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
209
291
|
addBugToReporter(bug, call);
|
|
210
292
|
}
|
|
211
293
|
}
|
|
212
|
-
else if (extType ==
|
|
294
|
+
else if (extType == AbsExtAPI::STRCAT)
|
|
213
295
|
{
|
|
214
296
|
if (!detectStrcat(as, call))
|
|
215
297
|
{
|
|
@@ -319,9 +401,9 @@ void BufOverflowDetector::updateGepObjOffsetFromBase(SVF::AddressValue gepAddrs,
|
|
|
319
401
|
*/
|
|
320
402
|
bool BufOverflowDetector::detectStrcpy(AbstractState& as, const CallICFGNode *call)
|
|
321
403
|
{
|
|
322
|
-
const
|
|
323
|
-
const
|
|
324
|
-
IntervalValue strLen = AbstractInterpretation::getAEInstance().getStrlen(as, arg1Val);
|
|
404
|
+
const SVFVar* arg0Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(0));
|
|
405
|
+
const SVFVar* arg1Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(1));
|
|
406
|
+
IntervalValue strLen = AbstractInterpretation::getAEInstance().getUtils()->getStrlen(as, arg1Val);
|
|
325
407
|
return canSafelyAccessMemory(as, arg0Val, strLen);
|
|
326
408
|
}
|
|
327
409
|
|
|
@@ -337,26 +419,24 @@ bool BufOverflowDetector::detectStrcpy(AbstractState& as, const CallICFGNode *ca
|
|
|
337
419
|
*/
|
|
338
420
|
bool BufOverflowDetector::detectStrcat(AbstractState& as, const CallICFGNode *call)
|
|
339
421
|
{
|
|
340
|
-
SVFIR* svfir = PAG::getPAG();
|
|
341
|
-
|
|
342
422
|
const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
|
|
343
423
|
const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
|
|
344
424
|
|
|
345
425
|
if (std::find(strcatGroup.begin(), strcatGroup.end(), call->getCalledFunction()->getName()) != strcatGroup.end())
|
|
346
426
|
{
|
|
347
|
-
const
|
|
348
|
-
const
|
|
349
|
-
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getStrlen(as, arg0Val);
|
|
350
|
-
IntervalValue strLen1 = AbstractInterpretation::getAEInstance().getStrlen(as, arg1Val);
|
|
427
|
+
const SVFVar* arg0Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(0));
|
|
428
|
+
const SVFVar* arg1Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(1));
|
|
429
|
+
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getUtils()->getStrlen(as, arg0Val);
|
|
430
|
+
IntervalValue strLen1 = AbstractInterpretation::getAEInstance().getUtils()->getStrlen(as, arg1Val);
|
|
351
431
|
IntervalValue totalLen = strLen0 + strLen1;
|
|
352
432
|
return canSafelyAccessMemory(as, arg0Val, totalLen);
|
|
353
433
|
}
|
|
354
434
|
else if (std::find(strncatGroup.begin(), strncatGroup.end(), call->getCalledFunction()->getName()) != strncatGroup.end())
|
|
355
435
|
{
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
IntervalValue arg2Num = as[
|
|
359
|
-
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getStrlen(as, arg0Val);
|
|
436
|
+
const SVFVar* arg0Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(0));
|
|
437
|
+
const SVFVar* arg2Val = AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(call->getArgument(2));
|
|
438
|
+
IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
|
|
439
|
+
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getUtils()->getStrlen(as, arg0Val);
|
|
360
440
|
IntervalValue totalLen = strLen0 + arg2Num;
|
|
361
441
|
return canSafelyAccessMemory(as, arg0Val, totalLen);
|
|
362
442
|
}
|
|
@@ -374,14 +454,14 @@ bool BufOverflowDetector::detectStrcat(AbstractState& as, const CallICFGNode *ca
|
|
|
374
454
|
* does not exceed the allocated size of the buffer.
|
|
375
455
|
*
|
|
376
456
|
* @param as Reference to the abstract state.
|
|
377
|
-
* @param value Pointer to the SVF
|
|
457
|
+
* @param value Pointer to the SVF var.
|
|
378
458
|
* @param len The interval value representing the length of the memory access.
|
|
379
459
|
* @return True if the memory access is safe, false otherwise.
|
|
380
460
|
*/
|
|
381
|
-
bool BufOverflowDetector::canSafelyAccessMemory(AbstractState& as, const SVF::
|
|
461
|
+
bool BufOverflowDetector::canSafelyAccessMemory(AbstractState& as, const SVF::SVFVar* value, const SVF::IntervalValue& len)
|
|
382
462
|
{
|
|
383
463
|
SVFIR* svfir = PAG::getPAG();
|
|
384
|
-
NodeID value_id =
|
|
464
|
+
NodeID value_id = value->getId();
|
|
385
465
|
|
|
386
466
|
assert(as[value_id].isAddr());
|
|
387
467
|
for (const auto& addr : as[value_id].getAddrs())
|