svf-tools 1.0.1254 → 1.0.1256
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1256",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -205,19 +205,12 @@ void AbstractInterpretation::handleGlobalNode()
|
|
|
205
205
|
handleSVFStatement(stmt);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
// BlkPtr
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// the analysis crashed on programs containing uninitialized BlkPtr. However,
|
|
215
|
-
// BlkPtr is semantically a *pointer* (address domain), not a numeric value
|
|
216
|
-
// (interval domain). Setting it to interval top broke cross-domain consistency:
|
|
217
|
-
// the interval domain and address domain gave contradictory information for the
|
|
218
|
-
// same variable. The correct representation is an AddressValue containing the
|
|
219
|
-
// BlackHole virtual address, which means "points to unknown memory".
|
|
220
|
-
abstractTrace[node][PAG::getPAG()->getBlkPtr()] = AddressValue(BlackHoleObjAddr);
|
|
208
|
+
// BlkPtr is the canonical unknown value. Keep its address-domain meaning
|
|
209
|
+
// for pointer uses, and also give it numeric top so external-input stores
|
|
210
|
+
// can flow through ordinary store/load state as [-inf, +inf].
|
|
211
|
+
AbstractValue blkPtrValue(IntervalValue::top());
|
|
212
|
+
blkPtrValue.getAddrs().insert(BlackHoleObjAddr);
|
|
213
|
+
abstractTrace[node][PAG::getPAG()->getBlkPtr()] = blkPtrValue;
|
|
221
214
|
}
|
|
222
215
|
|
|
223
216
|
/// Pull-based state merge: for each predecessor that has an abstract state,
|
|
@@ -1361,4 +1354,3 @@ void AbstractInterpretation::updateStateOnCopy(const CopyStmt *copy)
|
|
|
1361
1354
|
}
|
|
1362
1355
|
|
|
1363
1356
|
|
|
1364
|
-
|
|
@@ -243,6 +243,7 @@ protected:
|
|
|
243
243
|
//@{
|
|
244
244
|
virtual const Type *getBaseTypeAndFlattenedFields(const Value *V, std::vector<AccessPath> &fields, const Value* szValue);
|
|
245
245
|
virtual void addComplexConsForExt(Value *D, Value *S, const Value* sz);
|
|
246
|
+
virtual void handleNondetArgStoreAtExtCall(const CallBase* cs, const CallICFGNode* callICFGNode);
|
|
246
247
|
virtual void handleExtCall(const CallBase* cs, const Function* callee);
|
|
247
248
|
//@}
|
|
248
249
|
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
#include "SVF-LLVM/SymbolTableBuilder.h"
|
|
33
33
|
#include "SVF-LLVM/ObjTypeInference.h"
|
|
34
34
|
#include "Graphs/CallGraph.h"
|
|
35
|
+
#include "Util/ExtAPI.h"
|
|
35
36
|
|
|
36
37
|
using namespace std;
|
|
37
38
|
using namespace SVF;
|
|
@@ -48,6 +49,44 @@ struct MemcpyField
|
|
|
48
49
|
const SVFType* elementType;
|
|
49
50
|
};
|
|
50
51
|
|
|
52
|
+
bool parseNondetArgStoreAtExtCall(const std::string& annotation, u32_t& firstArg)
|
|
53
|
+
{
|
|
54
|
+
const std::string prefix = "STORE_TOP:Arg";
|
|
55
|
+
const size_t start = annotation.find(prefix);
|
|
56
|
+
if (start == std::string::npos)
|
|
57
|
+
return false;
|
|
58
|
+
|
|
59
|
+
size_t idx = start + prefix.size();
|
|
60
|
+
if (idx >= annotation.size() || annotation[idx] < '0' || annotation[idx] > '9')
|
|
61
|
+
return false;
|
|
62
|
+
|
|
63
|
+
firstArg = 0;
|
|
64
|
+
do
|
|
65
|
+
{
|
|
66
|
+
firstArg = firstArg * 10 + static_cast<u32_t>(annotation[idx] - '0');
|
|
67
|
+
++idx;
|
|
68
|
+
}
|
|
69
|
+
while (idx < annotation.size() && annotation[idx] >= '0' && annotation[idx] <= '9');
|
|
70
|
+
|
|
71
|
+
return idx < annotation.size() && annotation[idx] == '+';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
bool hasNondetArgStoreAtExtCall(const CallICFGNode* callICFGNode)
|
|
75
|
+
{
|
|
76
|
+
const FunObjVar* extFun = callICFGNode->getCalledFunction();
|
|
77
|
+
if (extFun == nullptr)
|
|
78
|
+
return false;
|
|
79
|
+
|
|
80
|
+
for (const std::string& annotation :
|
|
81
|
+
ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
|
|
82
|
+
{
|
|
83
|
+
u32_t firstArg = 0;
|
|
84
|
+
if (parseNondetArgStoreAtExtCall(annotation, firstArg))
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
51
90
|
void collectMemcpyFields(
|
|
52
91
|
const Type* llvmType,
|
|
53
92
|
const SVFType* svfType,
|
|
@@ -209,41 +248,40 @@ void SVFIRBuilder::addComplexConsForExt(Value *D, Value *S, const Value* szValue
|
|
|
209
248
|
const SVFType* srcSVFType = llvmModuleSet()->getSVFType(srcLayoutType);
|
|
210
249
|
std::vector<MemcpyField> dstMemcpyFields = getMemcpyFields(D, dstLayoutType, dstSVFType);
|
|
211
250
|
std::vector<MemcpyField> srcMemcpyFields = getMemcpyFields(S, srcLayoutType, srcSVFType);
|
|
212
|
-
if (dstMemcpyFields.empty()
|
|
213
|
-
goto fallback_memcpy_copy;
|
|
214
|
-
|
|
215
|
-
std::unordered_map<APOffset, MemcpyField> srcFieldsByByteOffset;
|
|
216
|
-
for (const auto& field : srcMemcpyFields)
|
|
217
|
-
srcFieldsByByteOffset.emplace(field.byteOffset, field);
|
|
218
|
-
|
|
219
|
-
const DataLayout& dl = llvmModuleSet()->getMainLLVMModule()->getDataLayout();
|
|
220
|
-
APOffset copyBytes = std::min<APOffset>(
|
|
221
|
-
static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(dstLayoutType))),
|
|
222
|
-
static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(srcLayoutType))));
|
|
223
|
-
if (szValue && SVFUtil::isa<ConstantInt>(szValue))
|
|
224
|
-
{
|
|
225
|
-
auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
|
|
226
|
-
copyBytes = std::min(copyBytes, static_cast<APOffset>(szIntVal.first));
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
for (const auto& dstField : dstMemcpyFields)
|
|
251
|
+
if (!dstMemcpyFields.empty() && !srcMemcpyFields.empty())
|
|
230
252
|
{
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
253
|
+
std::unordered_map<APOffset, MemcpyField> srcFieldsByByteOffset;
|
|
254
|
+
for (const auto& field : srcMemcpyFields)
|
|
255
|
+
srcFieldsByByteOffset.emplace(field.byteOffset, field);
|
|
256
|
+
|
|
257
|
+
const DataLayout& dl = llvmModuleSet()->getMainLLVMModule()->getDataLayout();
|
|
258
|
+
APOffset copyBytes = std::min<APOffset>(
|
|
259
|
+
static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(dstLayoutType))),
|
|
260
|
+
static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(srcLayoutType))));
|
|
261
|
+
if (szValue && SVFUtil::isa<ConstantInt>(szValue))
|
|
262
|
+
{
|
|
263
|
+
auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
|
|
264
|
+
copyBytes = std::min(copyBytes, static_cast<APOffset>(szIntVal.first));
|
|
265
|
+
}
|
|
236
266
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
267
|
+
for (const auto& dstField : dstMemcpyFields)
|
|
268
|
+
{
|
|
269
|
+
if (dstField.byteOffset >= copyBytes)
|
|
270
|
+
continue;
|
|
271
|
+
auto it = srcFieldsByByteOffset.find(dstField.byteOffset);
|
|
272
|
+
if (it == srcFieldsByByteOffset.end())
|
|
273
|
+
continue;
|
|
274
|
+
|
|
275
|
+
NodeID dField = getGepValVar(dstFieldBase, dstField.accessPath, dstField.elementType);
|
|
276
|
+
NodeID sField = getGepValVar(srcFieldBase, it->second.accessPath, it->second.elementType);
|
|
277
|
+
NodeID dummy = pag->addDummyValNode();
|
|
278
|
+
addLoadEdge(sField, dummy);
|
|
279
|
+
addStoreEdge(dummy, dField);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
242
282
|
}
|
|
243
|
-
return;
|
|
244
283
|
}
|
|
245
284
|
|
|
246
|
-
fallback_memcpy_copy:
|
|
247
285
|
//For each field (i), add (Ti = *S + i) and (*D + i = Ti).
|
|
248
286
|
for (u32_t index = 0; index < sz; index++)
|
|
249
287
|
{
|
|
@@ -260,11 +298,52 @@ fallback_memcpy_copy:
|
|
|
260
298
|
}
|
|
261
299
|
}
|
|
262
300
|
|
|
301
|
+
void SVFIRBuilder::handleNondetArgStoreAtExtCall(const CallBase* cs, const CallICFGNode* callICFGNode)
|
|
302
|
+
{
|
|
303
|
+
Set<u32_t> storeTopArgs;
|
|
304
|
+
const FunObjVar* extFun = callICFGNode->getCalledFunction();
|
|
305
|
+
if (extFun)
|
|
306
|
+
{
|
|
307
|
+
for (const std::string& annotation :
|
|
308
|
+
ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
|
|
309
|
+
{
|
|
310
|
+
u32_t firstArg = 0;
|
|
311
|
+
if (!parseNondetArgStoreAtExtCall(annotation, firstArg))
|
|
312
|
+
continue;
|
|
313
|
+
if (firstArg >= cs->arg_size())
|
|
314
|
+
continue;
|
|
315
|
+
|
|
316
|
+
for (u32_t argIdx = firstArg; argIdx < cs->arg_size(); ++argIdx)
|
|
317
|
+
storeTopArgs.insert(argIdx);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
for (u32_t argIdx : storeTopArgs)
|
|
322
|
+
{
|
|
323
|
+
const Value* arg = cs->getArgOperand(argIdx);
|
|
324
|
+
if (!arg->getType()->isPointerTy())
|
|
325
|
+
continue;
|
|
326
|
+
|
|
327
|
+
const Type* storedType =
|
|
328
|
+
LLVMModuleSet::getLLVMModuleSet()->getTypeInference()->inferObjType(arg);
|
|
329
|
+
NodeID src = pag->getBlkPtr();
|
|
330
|
+
NodeID dst = getValueNode(arg);
|
|
331
|
+
if (NodeID fieldZero = getDirectAccessFieldZeroValVar(arg, storedType))
|
|
332
|
+
dst = fieldZero;
|
|
333
|
+
if (src && dst)
|
|
334
|
+
addStoreEdge(src, dst);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
263
338
|
void SVFIRBuilder::handleExtCall(const CallBase* cs, const Function* callee)
|
|
264
339
|
{
|
|
265
340
|
const CallICFGNode *callICFGNode = llvmModuleSet()->getCallICFGNode(cs);
|
|
266
341
|
|
|
267
|
-
if (
|
|
342
|
+
if (hasNondetArgStoreAtExtCall(callICFGNode))
|
|
343
|
+
{
|
|
344
|
+
handleNondetArgStoreAtExtCall(cs, callICFGNode);
|
|
345
|
+
}
|
|
346
|
+
else if (isHeapAllocExtCallViaRet(callICFGNode))
|
|
268
347
|
{
|
|
269
348
|
NodeID val = llvmModuleSet()->getValueNode(cs);
|
|
270
349
|
NodeID obj = llvmModuleSet()->getObjectNode(cs);
|
package/svf-llvm/lib/extapi.c
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
MEMSET, // memcpy() operations
|
|
19
19
|
MEMCPY, // memset() operations
|
|
20
20
|
OVERWRITE, // svf function overwrite app function
|
|
21
|
+
STORE_TOP:Argi+, // store nondeterministic top values through argument i and following arguments
|
|
21
22
|
*/
|
|
22
23
|
__attribute__((annotate("ALLOC_HEAP_RET"), annotate("AllocSize:Arg0")))
|
|
23
24
|
void *malloc(unsigned long size)
|
|
@@ -805,6 +806,42 @@ unsigned long iconv(void* cd, char **__restrict inbuf, unsigned long *__restrict
|
|
|
805
806
|
return 0;
|
|
806
807
|
}
|
|
807
808
|
|
|
809
|
+
__attribute__((annotate("STORE_TOP:Arg1+")))
|
|
810
|
+
int scanf(const char *format, ...)
|
|
811
|
+
{
|
|
812
|
+
return 0;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
__attribute__((annotate("STORE_TOP:Arg1+")))
|
|
816
|
+
int __isoc99_scanf(const char *format, ...)
|
|
817
|
+
{
|
|
818
|
+
return 0;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
__attribute__((annotate("STORE_TOP:Arg2+")))
|
|
822
|
+
int fscanf(void *stream, const char *format, ...)
|
|
823
|
+
{
|
|
824
|
+
return 0;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
__attribute__((annotate("STORE_TOP:Arg2+")))
|
|
828
|
+
int __isoc99_fscanf(void *stream, const char *format, ...)
|
|
829
|
+
{
|
|
830
|
+
return 0;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
__attribute__((annotate("STORE_TOP:Arg2+")))
|
|
834
|
+
int sscanf(const char *str, const char *format, ...)
|
|
835
|
+
{
|
|
836
|
+
return 0;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
__attribute__((annotate("STORE_TOP:Arg2+")))
|
|
840
|
+
int __isoc99_sscanf(const char *str, const char *format, ...)
|
|
841
|
+
{
|
|
842
|
+
return 0;
|
|
843
|
+
}
|
|
844
|
+
|
|
808
845
|
__attribute__((annotate("OVERWRITE")))
|
|
809
846
|
void* _ZNSt5arrayIPK1ALm2EE4backEv(void *arg)
|
|
810
847
|
{
|