Static Value-Flow Analysis
AbsExtAPI.cpp
Go to the documentation of this file.
1 //===- AbsExtAPI.cpp -- Abstract Interpretation External API handler-----//
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/9/9.
26 //
27 #include "AE/Svfexe/AbsExtAPI.h"
29 
30 using namespace SVF;
32 {
33  svfir = PAG::getPAG();
34  icfg = svfir->getICFG();
35  initExtFunMap();
36 }
37 
39 {
40 #define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
41  auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
42  /* run real ext function */ \
43  AbstractState& as = getAbsStateFromTrace(callNode); \
44  u32_t rhs_id = callNode->getArgument(0)->getId(); \
45  if (!as.inVarToValTable(rhs_id)) return; \
46  u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
47  s32_t res = FUNC_NAME(rhs); \
48  u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId(); \
49  as[lhsId] = IntervalValue(res); \
50  return; \
51  }; \
52  func_map[#FUNC_NAME] = sse_##FUNC_NAME;
53 
65  SSE_FUNC_PROCESS(llvm.sin.f64, sin);
66  SSE_FUNC_PROCESS(llvm.cos.f64, cos);
67  SSE_FUNC_PROCESS(llvm.tan.f64, tan);
68  SSE_FUNC_PROCESS(llvm.log.f64, log);
69  SSE_FUNC_PROCESS(sinh, sinh);
70  SSE_FUNC_PROCESS(cosh, cosh);
71  SSE_FUNC_PROCESS(tanh, tanh);
72 
73  auto sse_svf_assert = [this](const CallICFGNode* callNode)
74  {
76  u32_t arg0 = callNode->getArgument(0)->getId();
77  AbstractState&as = getAbsStateFromTrace(callNode);
78  if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
79  {
80  SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
81  }
82  else
83  {
84  SVFUtil::errs() <<"svf_assert Fail. " << callNode->toString() << "\n";
85  assert(false);
86  }
87  return;
88  };
89  func_map["svf_assert"] = sse_svf_assert;
90 
91  auto svf_assert_eq = [this](const CallICFGNode* callNode)
92  {
93  u32_t arg0 = callNode->getArgument(0)->getId();
94  u32_t arg1 = callNode->getArgument(1)->getId();
95  AbstractState&as = getAbsStateFromTrace(callNode);
96  if (as[arg0].getInterval().equals(as[arg1].getInterval()))
97  {
98  SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
99  }
100  else
101  {
102  SVFUtil::errs() <<"svf_assert_eq Fail. " << callNode->toString() << "\n";
103  assert(false);
104  }
105  return;
106  };
107  func_map["svf_assert_eq"] = svf_assert_eq;
108 
109  auto svf_print = [&](const CallICFGNode* callNode)
110  {
111  if (callNode->arg_size() < 2) return;
112  AbstractState&as = getAbsStateFromTrace(callNode);
113  u32_t num_id = callNode->getArgument(0)->getId();
114  std::string text = strRead(as, callNode->getArgument(1));
115  assert(as.inVarToValTable(num_id) && "print() should pass integer");
116  IntervalValue itv = as[num_id].getInterval();
117  std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
118  << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
119  return;
120  };
121  func_map["svf_print"] = svf_print;
122 
123  auto svf_set_value = [&](const CallICFGNode* callNode)
124  {
125  if (callNode->arg_size() < 2) return;
126  AbstractState&as = getAbsStateFromTrace(callNode);
127  AbstractValue& num = as[callNode->getArgument(0)->getId()];
128  AbstractValue& lb = as[callNode->getArgument(1)->getId()];
129  AbstractValue& ub = as[callNode->getArgument(2)->getId()];
130  assert(lb.getInterval().is_numeral() && ub.getInterval().is_numeral());
131  num.getInterval().set_to_top();
133  const ICFGNode* node = SVFUtil::cast<ICFGNode>(
134  SVFUtil::cast<ValVar>(callNode->getArgument(0))->getGNode());
135  for (const SVFStmt* stmt: node->getSVFStmts())
136  {
137  if (SVFUtil::isa<LoadStmt>(stmt))
138  {
139  const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
140  NodeID rhsId = load->getRHSVarID();
141  as.storeValue(rhsId, num);
142  }
143  }
144  return;
145  };
146  func_map["set_value"] = svf_set_value;
147 
148  auto sse_scanf = [&](const CallICFGNode* callNode)
149  {
150  AbstractState& as = getAbsStateFromTrace(callNode);
151  //scanf("%d", &data);
152  if (callNode->arg_size() < 2) return;
153 
154  u32_t dst_id = callNode->getArgument(1)->getId();
155  if (!as.inVarToAddrsTable(dst_id))
156  {
157  return;
158  }
159  else
160  {
161  AbstractValue Addrs = as[dst_id];
162  for (auto vaddr: Addrs.getAddrs())
163  {
164  u32_t objId = AbstractState::getInternalID(vaddr);
166  as.store(vaddr, range);
167  }
168  }
169  };
170  auto sse_fscanf = [&](const CallICFGNode* callNode)
171  {
172  //fscanf(stdin, "%d", &data);
173  if (callNode->arg_size() < 3) return;
174  AbstractState& as = getAbsStateFromTrace(callNode);
175  u32_t dst_id = callNode->getArgument(2)->getId();
176  if (!as.inVarToAddrsTable(dst_id))
177  {
178  }
179  else
180  {
181  AbstractValue Addrs = as[dst_id];
182  for (auto vaddr: Addrs.getAddrs())
183  {
184  u32_t objId = AbstractState::getInternalID(vaddr);
186  as.store(vaddr, range);
187  }
188  }
189  };
190 
191  func_map["__isoc99_fscanf"] = sse_fscanf;
192  func_map["__isoc99_scanf"] = sse_scanf;
193  func_map["__isoc99_vscanf"] = sse_scanf;
194  func_map["fscanf"] = sse_fscanf;
195  func_map["scanf"] = sse_scanf;
196  func_map["sscanf"] = sse_scanf;
197  func_map["__isoc99_sscanf"] = sse_scanf;
198  func_map["vscanf"] = sse_scanf;
199 
200  auto sse_fread = [&](const CallICFGNode *callNode)
201  {
202  if (callNode->arg_size() < 3) return;
203  AbstractState&as = getAbsStateFromTrace(callNode);
204  u32_t block_count_id = callNode->getArgument(2)->getId();
205  u32_t block_size_id = callNode->getArgument(1)->getId();
206  IntervalValue block_count = as[block_count_id].getInterval();
207  IntervalValue block_size = as[block_size_id].getInterval();
208  IntervalValue block_byte = block_count * block_size;
209  };
210  func_map["fread"] = sse_fread;
211 
212  auto sse_sprintf = [&](const CallICFGNode *callNode)
213  {
214  // printf is difficult to predict since it has no byte size arguments
215  };
216 
217  auto sse_snprintf = [&](const CallICFGNode *callNode)
218  {
219  if (callNode->arg_size() < 2) return;
220  AbstractState&as = getAbsStateFromTrace(callNode);
221  u32_t size_id = callNode->getArgument(1)->getId();
222  u32_t dst_id = callNode->getArgument(0)->getId();
223  // get elem size of arg2
224  u32_t elemSize = 1;
225  if (callNode->getArgument(2)->getType()->isArrayTy())
226  {
227  elemSize = SVFUtil::dyn_cast<SVFArrayType>(
228  callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
229  }
230  else if (callNode->getArgument(2)->getType()->isPointerTy())
231  {
232  elemSize = as.getPointeeElement(callNode->getArgument(2)->getId())->getByteSize();
233  }
234  else
235  {
236  return;
237  // assert(false && "we cannot support this type");
238  }
239  IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
240  if (!as.inVarToAddrsTable(dst_id))
241  {
242  }
243  };
244  func_map["__snprintf_chk"] = sse_snprintf;
245  func_map["__vsprintf_chk"] = sse_sprintf;
246  func_map["__sprintf_chk"] = sse_sprintf;
247  func_map["snprintf"] = sse_snprintf;
248  func_map["sprintf"] = sse_sprintf;
249  func_map["vsprintf"] = sse_sprintf;
250  func_map["vsnprintf"] = sse_snprintf;
251  func_map["__vsnprintf_chk"] = sse_snprintf;
252  func_map["swprintf"] = sse_snprintf;
253  func_map["_snwprintf"] = sse_snprintf;
254 
255 
256  auto sse_itoa = [&](const CallICFGNode* callNode)
257  {
258  // itoa(num, ch, 10);
259  // num: int, ch: char*, 10 is decimal
260  if (callNode->arg_size() < 3) return;
261  AbstractState&as = getAbsStateFromTrace(callNode);
262  u32_t num_id = callNode->getArgument(0)->getId();
263 
264  u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
265  std::string snum = std::to_string(num);
266  };
267  func_map["itoa"] = sse_itoa;
268 
269 
270  auto sse_strlen = [&](const CallICFGNode *callNode)
271  {
272  // check the arg size
273  if (callNode->arg_size() < 1) return;
274  const SVFVar* strValue = callNode->getArgument(0);
275  AbstractState& as = getAbsStateFromTrace(callNode);
276  NodeID value_id = strValue->getId();
277  u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
278  u32_t dst_size = 0;
279  for (const auto& addr : as[value_id].getAddrs())
280  {
281  NodeID objId = AbstractState::getInternalID(addr);
282  if (svfir->getBaseObj(objId)->isConstantByteSize())
283  {
284  dst_size = svfir->getBaseObj(objId)->getByteSizeOfObj();
285  }
286  else
287  {
288  const ICFGNode* addrNode = SVFUtil::cast<ICFGNode>(svfir->getBaseObj(objId)->getGNode());
289  for (const SVFStmt* stmt2: addrNode->getSVFStmts())
290  {
291  if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
292  {
293  dst_size = as.getAllocaInstByteSize(addrStmt);
294  }
295  }
296  }
297  }
298  u32_t len = 0;
299  NodeID dstid = strValue->getId();
300  if (as.inVarToAddrsTable(dstid))
301  {
302  for (u32_t index = 0; index < dst_size; index++)
303  {
304  AbstractValue expr0 =
305  as.getGepObjAddrs(dstid, IntervalValue(index));
306  AbstractValue val;
307  for (const auto &addr: expr0.getAddrs())
308  {
309  val.join_with(as.load(addr));
310  }
311  if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
312  {
313  break;
314  }
315  ++len;
316  }
317  }
318  if (len == 0)
319  {
320  as[lhsId] = IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit());
321  }
322  else
323  {
324  as[lhsId] = IntervalValue(len);
325  }
326  };
327  func_map["strlen"] = sse_strlen;
328  func_map["wcslen"] = sse_strlen;
329 
330  auto sse_recv = [&](const CallICFGNode *callNode)
331  {
332  // recv(sockfd, buf, len, flags);
333  if (callNode->arg_size() < 4) return;
334  AbstractState&as = getAbsStateFromTrace(callNode);
335  u32_t len_id = callNode->getArgument(2)->getId();
336  IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
337  u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
338  as[lhsId] = len;
339  };
340  func_map["recv"] = sse_recv;
341  func_map["__recv"] = sse_recv;
342 };
343 
345 {
346  const ICFGNode* repNode = icfg->getRepNode(node);
347  if (abstractTrace.count(repNode) == 0)
348  {
349  assert(0 && "No preAbsTrace for this node");
350  }
351  else
352  {
353  return abstractTrace[repNode];
354  }
355 }
356 
358 {
359  // sse read string nodeID->string
360  std::string str0;
361 
362  for (u32_t index = 0; index < Options::MaxFieldLimit(); index++)
363  {
364  // dead loop for string and break if there's a \0. If no \0, it will throw err.
365  if (!as.inVarToAddrsTable(rhs->getId())) continue;
366  AbstractValue expr0 =
368 
369  AbstractValue val;
370  for (const auto &addr: expr0.getAddrs())
371  {
372  val.join_with(as.load(addr));
373  }
374  if (!val.getInterval().is_numeral())
375  {
376  break;
377  }
378  if ((char) val.getInterval().getIntNumeral() == '\0')
379  {
380  break;
381  }
382  str0.push_back((char) val.getInterval().getIntNumeral());
383  }
384  return str0;
385 }
386 
388 {
390  const SVFFunction *fun = call->getCalledFunction();
391  assert(fun && "SVFFunction* is nullptr");
392  ExtAPIType extType = UNCLASSIFIED;
393  // get type of mem api
394  for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
395  {
396  if (annotation.find("MEMCPY") != std::string::npos)
397  extType = MEMCPY;
398  if (annotation.find("MEMSET") != std::string::npos)
399  extType = MEMSET;
400  if (annotation.find("STRCPY") != std::string::npos)
401  extType = STRCPY;
402  if (annotation.find("STRCAT") != std::string::npos)
403  extType = STRCAT;
404  }
405  if (extType == UNCLASSIFIED)
406  {
407  if (func_map.find(fun->getName()) != func_map.end())
408  {
409  func_map[fun->getName()](call);
410  }
411  else
412  {
413  if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
414  {
415  u32_t lhsId = ret->getId();
416  if (as.inVarToAddrsTable(lhsId))
417  {
418 
419  }
420  else
421  {
422  as[lhsId] = IntervalValue();
423  }
424  }
425  return;
426  }
427  }
428  // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
429  else if (extType == MEMCPY)
430  {
431  IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
432  svfir->getGNode(call->getArgument(0)->getId());
433  handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
434  }
435  else if (extType == MEMSET)
436  {
437  // memset dst is arg0, elem is arg1, size is arg2
438  IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
439  IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
440  handleMemset(as, call->getArgument(0), elem, len);
441  }
442  else if (extType == STRCPY)
443  {
444  handleStrcpy(call);
445  }
446  else if (extType == STRCAT)
447  {
448  handleStrcat(call);
449  }
450  else
451  {
452 
453  }
454  return;
455 }
456 
458 {
459  // strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
460  // get the dst and src
462  const SVFVar* arg0Val = call->getArgument(0);
463  const SVFVar* arg1Val = call->getArgument(1);
464  IntervalValue strLen = getStrlen(as, arg1Val);
465  // no need to -1, since it has \0 as the last byte
466  handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
467 }
468 
470 {
471  NodeID value_id = strValue->getId();
472  u32_t dst_size = 0;
473  for (const auto& addr : as[value_id].getAddrs())
474  {
475  NodeID objId = AbstractState::getInternalID(addr);
476  if (svfir->getBaseObj(objId)->isConstantByteSize())
477  {
478  dst_size = svfir->getBaseObj(objId)->getByteSizeOfObj();
479  }
480  else
481  {
482  const ICFGNode* icfgNode = SVFUtil::cast<ICFGNode>( svfir->getBaseObj(objId)->getGNode());
483  for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
484  {
485  if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
486  {
487  dst_size = as.getAllocaInstByteSize(addrStmt);
488  }
489  }
490  }
491  }
492  u32_t len = 0;
493  u32_t elemSize = 1;
494  if (as.inVarToAddrsTable(value_id))
495  {
496  for (u32_t index = 0; index < dst_size; index++)
497  {
498  AbstractValue expr0 =
499  as.getGepObjAddrs(value_id, IntervalValue(index));
500  AbstractValue val;
501  for (const auto &addr: expr0.getAddrs())
502  {
503  val.join_with(as.load(addr));
504  }
505  if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
506  {
507  break;
508  }
509  ++len;
510  }
511  if (strValue->getType()->isArrayTy())
512  {
513  elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
514  }
515  else if (strValue->getType()->isPointerTy())
516  {
517  if (const SVFType* elemType = as.getPointeeElement(value_id))
518  {
519  if (elemType->isArrayTy())
520  elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
521  else
522  elemSize = elemType->getByteSize();
523  }
524  else
525  {
526  elemSize = 1;
527  }
528  }
529  else
530  {
531  assert(false && "we cannot support this type");
532  }
533  }
534  if (len == 0)
535  {
537  }
538  else
539  {
540  return IntervalValue(len * elemSize);
541  }
542 }
543 
544 
546 {
547  // __strcat_chk, strcat, __wcscat_chk, wcscat, __strncat_chk, strncat, __wcsncat_chk, wcsncat
548  // to check it is strcat group or strncat group
550  const SVFFunction *fun = call->getCalledFunction();
551  const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
552  const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
553  if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
554  {
555  const SVFVar* arg0Val = call->getArgument(0);
556  const SVFVar* arg1Val = call->getArgument(1);
557  IntervalValue strLen0 = getStrlen(as, arg0Val);
558  IntervalValue strLen1 = getStrlen(as, arg1Val);
559  IntervalValue totalLen = strLen0 + strLen1;
560  handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
561  // do memcpy
562  }
563  else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
564  {
565  const SVFVar* arg0Val = call->getArgument(0);
566  const SVFVar* arg1Val = call->getArgument(1);
567  const SVFVar* arg2Val = call->getArgument(2);
568  IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
569  IntervalValue strLen0 = getStrlen(as, arg0Val);
570  IntervalValue totalLen = strLen0 + arg2Num;
571  handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
572  // do memcpy
573  }
574  else
575  {
576  assert(false && "unknown strcat function, please add it to strcatGroup or strncatGroup");
577  }
578 }
579 
580 void AbsExtAPI::handleMemcpy(AbstractState& as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
581 {
582  u32_t dstId = dst->getId(); // pts(dstId) = {objid} objbar objtypeinfo->getType().
583  u32_t srcId = src->getId();
584  u32_t elemSize = 1;
585  if (dst->getType()->isArrayTy())
586  {
587  elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
588  }
589  // memcpy(i32*, i32*, 40)
590  else if (dst->getType()->isPointerTy())
591  {
592  if (const SVFType* elemType = as.getPointeeElement(dstId))
593  {
594  if (elemType->isArrayTy())
595  elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
596  else
597  elemSize = elemType->getByteSize();
598  }
599  else
600  {
601  elemSize = 1;
602  }
603  }
604  else
605  {
606  assert(false && "we cannot support this type");
607  }
608  u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
609  u32_t range_val = size / elemSize;
610  if (as.inVarToAddrsTable(srcId) && as.inVarToAddrsTable(dstId))
611  {
612  for (u32_t index = 0; index < range_val; index++)
613  {
614  // dead loop for string and break if there's a \0. If no \0, it will throw err.
615  AbstractValue expr_src =
616  as.getGepObjAddrs(srcId, IntervalValue(index));
617  AbstractValue expr_dst =
618  as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
619  for (const auto &dst: expr_dst.getAddrs())
620  {
621  for (const auto &src: expr_src.getAddrs())
622  {
623  u32_t objId = AbstractState::getInternalID(src);
624  if (as.inAddrToValTable(objId))
625  {
626  as.store(dst, as.load(src));
627  }
628  else if (as.inAddrToAddrsTable(objId))
629  {
630  as.store(dst, as.load(src));
631  }
632  }
633  }
634  }
635  }
636 }
637 
639 {
640  u32_t dstId = dst->getId();
641  u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
642  u32_t elemSize = 1;
643  if (dst->getType()->isArrayTy())
644  {
645  elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
646  }
647  else if (dst->getType()->isPointerTy())
648  {
649  if (const SVFType* elemType = as.getPointeeElement(dstId))
650  {
651  elemSize = elemType->getByteSize();
652  }
653  else
654  {
655  elemSize = 1;
656  }
657  }
658  else
659  {
660  assert(false && "we cannot support this type");
661  }
662 
663  u32_t range_val = size / elemSize;
664  for (u32_t index = 0; index < range_val; index++)
665  {
666  // dead loop for string and break if there's a \0. If no \0, it will throw err.
667  if (as.inVarToAddrsTable(dstId))
668  {
669  AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
670  for (const auto &addr: lhs_gep.getAddrs())
671  {
672  u32_t objId = AbstractState::getInternalID(addr);
673  if (as.inAddrToValTable(objId))
674  {
675  AbstractValue tmp = as.load(addr);
676  tmp.join_with(elem);
677  as.store(addr, tmp);
678  }
679  else
680  {
681  as.store(addr, elem);
682  }
683  }
684  }
685  else
686  break;
687  }
688 }
689 
702 {
703  if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
704  {
705  u32_t bits = type->getByteSize() * 8;
706  s64_t ub = 0;
707  s64_t lb = 0;
708  if (bits >= 32)
709  {
710  if (intType->isSigned())
711  {
712  ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
713  lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
714  }
715  else
716  {
717  ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
718  lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
719  }
720  }
721  else if (bits == 16)
722  {
723  if (intType->isSigned())
724  {
725  ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
726  lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
727  }
728  else
729  {
730  ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
731  lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
732  }
733  }
734  else if (bits == 8)
735  {
736  if (intType->isSigned())
737  {
738  ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
739  lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
740  }
741  else
742  {
743  ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
744  lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
745  }
746  }
747  return IntervalValue(lb, ub);
748  }
749  else if (SVFUtil::isa<SVFOtherType>(type))
750  {
751  // handle other type like float double, set s32_t as the range
752  s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
753  s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
754  return IntervalValue(lb, ub);
755  }
756  else
757  {
758  return IntervalValue::top();
759  // other types, return top interval
760  }
761 }
762 
764 {
765  assert(svfir->hasGNode(svfir->getValueNode(val)));
766  return svfir->getGNode(svfir->getValueNode(val));
767 }
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
newitem type
Definition: cJSON.cpp:2739
int index
Definition: cJSON.h:170
const char *const string
Definition: cJSON.h:172
std::string strRead(AbstractState &as, const SVFVar *rhs)
Reads a string from the abstract state.
Definition: AbsExtAPI.cpp:357
void handleMemset(AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
Handles the memset API call.
Definition: AbsExtAPI.cpp:638
void initExtFunMap()
Initializes the external function map.
Definition: AbsExtAPI.cpp:38
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.
Definition: AbsExtAPI.cpp:469
Map< const ICFGNode *, AbstractState > & abstractTrace
Map of ICFG nodes to abstract states.
Definition: AbsExtAPI.h:143
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
Definition: AbsExtAPI.cpp:387
AbsExtAPI(Map< const ICFGNode *, AbstractState > &traces)
Constructor for AbsExtAPI.
Definition: AbsExtAPI.cpp:31
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
Definition: AbsExtAPI.cpp:344
const SVFVar * getSVFVar(const SVFValue *val)
Retrieves the SVF variable from a given SVF value.
Definition: AbsExtAPI.cpp:763
void handleMemcpy(AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
Handles the memcpy API call.
Definition: AbsExtAPI.cpp:580
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition: AbsExtAPI.h:141
void handleStrcat(const SVF::CallICFGNode *call)
Handles the strcat API call.
Definition: AbsExtAPI.cpp:545
ExtAPIType
Enumeration of external API types.
Definition: AbsExtAPI.h:52
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
Definition: AbsExtAPI.cpp:701
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition: AbsExtAPI.h:142
void handleStrcpy(const CallICFGNode *call)
Handles the strcpy API call.
Definition: AbsExtAPI.cpp:457
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
Definition: AbsExtAPI.h:144
Set< const CallICFGNode * > checkpoints
static AbstractInterpretation & getAEInstance()
u32_t getAllocaInstByteSize(const AddrStmt *addr)
void store(u32_t addr, const AbstractValue &val)
virtual bool inAddrToValTable(u32_t id) const
whether the memory address stores abstract value
bool inAddrToAddrsTable(u32_t id) const
whether the memory address stores memory addresses
std::string toString() const
const SVFType * getPointeeElement(NodeID id)
virtual AbstractValue & load(u32_t addr)
bool inVarToAddrsTable(u32_t id) const
whether the variable is in varToAddrs table
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
virtual bool inVarToValTable(u32_t id) const
whether the variable is in varToVal table
void storeValue(NodeID varId, AbstractValue val)
AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset)
void join_with(const AbstractValue &other)
AddressValue & getAddrs()
IntervalValue & getInterval()
NodeID getRHSVarID() const
s64_t getIntNumeral() const
Definition: NumericValue.h:703
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition: ICFGNode.h:457
const SVFVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition: ICFGNode.h:500
static ExtAPI * getExtAPI()
Definition: ExtAPI.cpp:42
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
bool hasGNode(NodeID id) const
Has a node.
Definition: GenericGraph.h:661
const SVFStmtList & getSVFStmts() const
Definition: ICFGNode.h:117
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition: ICFG.h:246
NodeID getValueNode(const SVFValue *V)
Definition: IRGraph.h:137
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
s64_t getIntNumeral() const
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
const BoundedInt & lb() const
Return the lower bound.
const std::string toString() const
const BoundedInt & ub() const
Return the upper bound.
void set_to_top()
Set current IntervalValue as top.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
Definition: IntervalValue.h:94
const SVFBaseNode * getGNode() const
Get the reference value to this object.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
bool isConstantByteSize() const
Check if byte size is a const value.
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition: Options.h:38
const SVFVar * getActualRet() const
Return actual return parameter.
Definition: ICFGNode.h:627
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
ICFG * getICFG() const
Definition: SVFIR.h:171
const MemObj * getBaseObj(NodeID id) const
Definition: SVFIR.h:459
bool isArrayTy() const
Definition: SVFType.h:254
bool isPointerTy() const
Definition: SVFType.h:249
u32_t getByteSize() const
Definition: SVFType.h:244
const std::string & getName() const
Definition: SVFValue.h:243
virtual const SVFType * getType() const
Return type of the value.
Definition: SVFVariables.h:96
int iscntrl(int c)
Definition: extapi.c:846
int isdigit(int c)
Definition: extapi.c:851
int isgraph(int c)
Definition: extapi.c:856
int isspace(char c)
Definition: extapi.c:876
int isprint(int c)
Definition: extapi.c:866
int ispunct(int argument)
Definition: extapi.c:871
int isblank(int character)
Definition: extapi.c:841
int isalnum(int character)
Definition: extapi.c:831
int isupper(int c)
Definition: extapi.c:881
int isxdigit(int c)
Definition: extapi.c:886
int isalpha(int character)
Definition: extapi.c:836
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition: SVFUtil.cpp:53
std::ostream & errs()
Overwrite llvm::errs()
Definition: SVFUtil.h:56
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
unsigned u32_t
Definition: GeneralType.h:46
signed long long s64_t
Definition: GeneralType.h:49