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.1254",
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": {
@@ -260,7 +260,6 @@ public:
260
260
  {
261
261
  return nullPtrSymID();
262
262
  }
263
-
264
263
  u32_t getValueNodeNum();
265
264
 
266
265
  u32_t getObjectNodeNum();
@@ -205,19 +205,12 @@ void AbstractInterpretation::handleGlobalNode()
205
205
  handleSVFStatement(stmt);
206
206
  }
207
207
 
208
- // BlkPtr represents a pointer whose target is statically unknown (e.g., from
209
- // int2ptr casts, external function returns, or unmodeled instructions like
210
- // AtomicCmpXchg). It should be an address pointing to the BlackHole object
211
- // (ID=2), NOT an interval top.
212
- //
213
- // History: this was originally set to IntervalValue::top() as a quick fix when
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() || srcMemcpyFields.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
- if (dstField.byteOffset >= copyBytes)
232
- continue;
233
- auto it = srcFieldsByByteOffset.find(dstField.byteOffset);
234
- if (it == srcFieldsByByteOffset.end())
235
- continue;
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
- NodeID dField = getGepValVar(dstFieldBase, dstField.accessPath, dstField.elementType);
238
- NodeID sField = getGepValVar(srcFieldBase, it->second.accessPath, it->second.elementType);
239
- NodeID dummy = pag->addDummyValNode();
240
- addLoadEdge(sField, dummy);
241
- addStoreEdge(dummy, dField);
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 (isHeapAllocExtCallViaRet(callICFGNode))
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);
@@ -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
  {