Static Value-Flow Analysis
SVFIR2AbsState.cpp
Go to the documentation of this file.
1 //===- SVFIR2AbsState.cpp -- SVF IR Translation to Interval Domain-----//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2022> <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  * SVFIR2AbsState.cpp
24  *
25  * Created on: Aug 7, 2022
26  * Author: Jiawei Wang, Xiao Cheng
27  *
28  */
29 
31 #include "Util/Options.h"
32 
33 using namespace SVF;
34 using namespace SVFUtil;
35 
37 
50 {
51  if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
52  {
53  u32_t bits = type->getByteSize() * 8;
54  s64_t ub = 0;
55  s64_t lb = 0;
56  if (bits >= 32)
57  {
58  if (intType->isSigned())
59  {
60  ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
61  lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
62  }
63  else
64  {
65  ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
66  lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
67  }
68  }
69  else if (bits == 16)
70  {
71  if (intType->isSigned())
72  {
73  ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
74  lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
75  }
76  else
77  {
78  ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
79  lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
80  }
81  }
82  else if (bits == 8)
83  {
84  if (intType->isSigned())
85  {
86  ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
87  lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
88  }
89  else
90  {
91  ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
92  lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
93  }
94  }
95  return IntervalValue(lb, ub);
96  }
97  else if (SVFUtil::isa<SVFOtherType>(type))
98  {
99  // handle other type like float double, set s32_t as the range
100  s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
101  s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
102  return IntervalValue(lb, ub);
103  }
104  else
105  {
106  return IntervalValue::top();
107  // other types, return top interval
108  }
109 }
110 
112 {
113  const SVFType* type = var->getType();
114  if (SVFUtil::isa<SVFIntegerType>(type))
115  {
116  u32_t bits = type->getByteSize() * 8;
117  if (as[var->getId()].getInterval().is_numeral())
118  {
119  if (bits == 8)
120  {
121  int8_t signed_i8_value = as[var->getId()].getInterval().getIntNumeral();
122  u32_t unsigned_value = static_cast<uint8_t>(signed_i8_value);
123  return IntervalValue(unsigned_value, unsigned_value);
124  }
125  else if (bits == 16)
126  {
127  s16_t signed_i16_value = as[var->getId()].getInterval().getIntNumeral();
128  u32_t unsigned_value = static_cast<u16_t>(signed_i16_value);
129  return IntervalValue(unsigned_value, unsigned_value);
130  }
131  else if (bits == 32)
132  {
133  s32_t signed_i32_value = as[var->getId()].getInterval().getIntNumeral();
134  u32_t unsigned_value = static_cast<u32_t>(signed_i32_value);
135  return IntervalValue(unsigned_value, unsigned_value);
136  }
137  else if (bits == 64)
138  {
139  s64_t signed_i64_value = as[var->getId()].getInterval().getIntNumeral();
140  return IntervalValue((s64_t)signed_i64_value, (s64_t)signed_i64_value);
141  // we only support i64 at most
142  }
143  else
144  {
145  assert(false && "cannot support int type other than u8/16/32/64");
146  }
147  }
148  else
149  {
150  return IntervalValue::top(); // TODO: may have better solution
151  }
152  }
153  return IntervalValue::top(); // TODO: may have better solution
154 }
155 
157 {
158  return as[var->getId()].getInterval();
159 }
160 
162 {
163  // IntervalValue are BoundedInt, so we can directly return the value
164  return getSExtValue(as, var);
165 }
166 
168 {
169  // IntervalValue are BoundedInt, so we can directly return the value
170  return getZExtValue(as, var);
171 }
172 
174 {
175  // IntervalValue are BoundedInt, so we can directly return the value
176  return getSExtValue(as, var);
177 }
178 
180 {
181  // IntervalValue are BoundedInt, so we can directly return the value
182  return getZExtValue(as, var);
183 }
184 
186 {
187  const IntervalValue& itv = as[var->getId()].getInterval();
188  if(itv.isBottom()) return itv;
189  // get the value of ub and lb
190  s64_t int_lb = itv.lb().getIntNumeral();
191  s64_t int_ub = itv.ub().getIntNumeral();
192  // get dst type
193  u32_t dst_bits = dstType->getByteSize() * 8;
194  if (dst_bits == 8)
195  {
196  // get the signed value of ub and lb
197  int8_t s8_lb = static_cast<int8_t>(int_lb);
198  int8_t s8_ub = static_cast<int8_t>(int_ub);
199  if (s8_lb > s8_ub)
200  {
201  // return range of s8
202  return IntervalValue::top();
203  }
204  return IntervalValue(s8_lb, s8_ub);
205  }
206  else if (dst_bits == 16)
207  {
208  // get the signed value of ub and lb
209  s16_t s16_lb = static_cast<s16_t>(int_lb);
210  s16_t s16_ub = static_cast<s16_t>(int_ub);
211  if (s16_lb > s16_ub)
212  {
213  // return range of s16
214  return IntervalValue::top();
215  }
216  return IntervalValue(s16_lb, s16_ub);
217  }
218  else if (dst_bits == 32)
219  {
220  // get the signed value of ub and lb
221  s32_t s32_lb = static_cast<s32_t>(int_lb);
222  s32_t s32_ub = static_cast<s32_t>(int_ub);
223  if (s32_lb > s32_ub)
224  {
225  // return range of s32
226  return IntervalValue::top();
227  }
228  return IntervalValue(s32_lb, s32_ub);
229  }
230  else
231  {
232  assert(false && "cannot support dst int type other than u8/16/32");
233  }
234 }
235 
237 {
238  // TODO: now we do not really handle fptrunc
239  return as[var->getId()].getInterval();
240 }
241 
243 {
244  for (const auto &rhsItem: rhs._varToAbsVal)
245  {
246  auto lhsIter = lhs._varToAbsVal.find(rhsItem.first);
247  if (lhsIter != lhs._varToAbsVal.end())
248  {
249  if (rhsItem.second.isAddr())
250  {
251  for (const auto &addr: rhsItem.second.getAddrs())
252  {
253  if (!lhsIter->second.getAddrs().contains(addr))
254  {
255  for (s32_t i = 0; i < (s32_t) Options::MaxFieldLimit(); i++)
256  {
257  lhsIter->second.join_with(getGepObjAddress(as, getInternalID(addr), i));
258  }
259  }
260  }
261  }
262  }
263  }
264  for (const auto &rhsItem: rhs._addrToAbsVal)
265  {
266  auto lhsIter = lhs._addrToAbsVal.find(rhsItem.first);
267  if (lhsIter != lhs._addrToAbsVal.end())
268  {
269  if (rhsItem.second.isAddr())
270  {
271  for (const auto& addr : rhsItem.second.getAddrs())
272  {
273  if (!lhsIter->second.getAddrs().contains(addr))
274  {
275  for (s32_t i = 0; i < (s32_t)Options::MaxFieldLimit();
276  i++)
277  {
278  lhsIter->second.join_with(
279  getGepObjAddress(as, getInternalID(addr), i));
280  }
281  }
282  }
283  }
284  }
285  }
286 }
287 
289 {
290  for (const auto &rhsItem: rhs._varToAbsVal)
291  {
292  auto lhsIter = lhs._varToAbsVal.find(rhsItem.first);
293  if (lhsIter != lhs._varToAbsVal.end())
294  {
295  if (lhsIter->second.isAddr())
296  {
297  for (const auto &addr: lhsIter->second.getAddrs())
298  {
299  if (!rhsItem.second.getAddrs().contains(addr))
300  {
301  lhsIter->second = rhsItem.second;
302  break;
303  }
304  }
305  }
306  }
307  }
308  for (const auto &rhsItem: rhs._addrToAbsVal)
309  {
310  auto lhsIter = lhs._addrToAbsVal.find(rhsItem.first);
311  if (lhsIter != lhs._addrToAbsVal.end())
312  {
313  if (lhsIter->second.isAddr())
314  {
315  for (const auto& addr : lhsIter->second.getAddrs())
316  {
317  if (!rhsItem.second.getAddrs().contains(addr))
318  {
319  lhsIter->second = rhsItem.second;
320  break;
321  }
322  }
323  }
324  }
325  }
326 }
327 
329 {
330  AbstractValue addrs = getAddrs(as, pointer);
331  AddressValue ret = AddressValue();
332  for (const auto &addr: addrs.getAddrs())
333  {
334  s64_t baseObj = getInternalID(addr);
335  assert(SVFUtil::isa<ObjVar>(_svfir->getGNode(baseObj)) && "Fail to get the base object address!");
336  NodeID gepObj = _svfir->getGepObjVar(baseObj, offset);
339  }
340  return ret;
341 }
342 
366 {
367  IntervalValue byte_res = IntervalValue(0);
368  for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
369  {
370  AccessPath::IdxOperandPair IdxVarAndType =
372  const SVFValue *value =
373  gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
374  const SVFType *type = IdxVarAndType.second;
375  s64_t idxLb = 0;
376  s64_t idxUb = 0;
377  s64_t byteLb = 0;
378  s64_t byteUb = 0;
379  // get lb and ub of the index value
380  if (const SVFConstantInt* constInt = SVFUtil::dyn_cast<SVFConstantInt>(value))
381  idxLb = idxUb = constInt->getSExtValue();
382  else
383  {
384  IntervalValue idxItv = as[_svfir->getValueNode(value)].getInterval();
385  if (idxItv.isBottom())
386  idxLb = idxUb = 0;
387  else
388  {
389  idxLb = idxItv.lb().getIntNumeral();
390  idxUb = idxItv.ub().getIntNumeral();
391  }
392  }
393  // for pointer type, elemByteSize * indexOperand
394  if (SVFUtil::isa<SVFPointerType>(type))
395  {
396  u32_t elemByte = gep->getAccessPath().gepSrcPointeeType()->getByteSize();
397  byteLb = (double)Options::MaxFieldLimit() / elemByte < idxLb? Options::MaxFieldLimit(): idxLb * elemByte;
398  byteUb = (double)Options::MaxFieldLimit() / elemByte < idxUb? Options::MaxFieldLimit(): idxUb * elemByte;
399 
400  }
401  // for array or struct, get flattened index from SymbolTable Info
402  // and then calculate the byte offset from beginning to the field of struct
403  else
404  {
406  {
407  const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()
408  ->getTypeInfo(type)
410  if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
411  {
412  byteLb = byteUb = 0;
413  }
414  else
415  {
417  type, idxLb);
419  type, idxUb);
420  for (u32_t idx = 0; idx < idxLb; ++idx)
421  {
423  byteLb += byte;
424  }
425  byteUb = byteLb;
426  for (u32_t idx = idxLb; idx < idxUb; ++idx)
427  {
429  byteUb += byte;
430  }
431  }
432  }
433  else
434  {
435  byteLb = byteUb = 0;
436  }
437 
438  }
439  byte_res = byte_res + IntervalValue(byteLb, byteUb);
440  }
441 
442  if (byte_res.isBottom())
443  {
444  byte_res = IntervalValue(0);
445  }
446  return byte_res;
447 }
448 
458 {
459  if (gep->isConstantOffset())
461  IntervalValue res = IntervalValue(0);
462  for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
463  {
464  AccessPath::IdxOperandPair IdxVarAndType =
466  const SVFValue *value =
467  gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
468  const SVFType *type = IdxVarAndType.second;
469  // idxLb/Ub is the flattened offset generated by the current OffsetVarAndGepTypePair
470  s64_t idxLb;
471  s64_t idxUb;
472  // get lb and ub of the index value
473  if (const SVFConstantInt* constInt = SVFUtil::dyn_cast<SVFConstantInt>(value))
474  idxLb = idxUb = constInt->getSExtValue();
475  else
476  {
477  IntervalValue idxItv = as[_svfir->getValueNode(value)].getInterval();
478  if (idxItv.isBottom())
479  idxLb = idxUb = 0;
480  else
481  {
482  idxLb = idxItv.lb().getIntNumeral();
483  idxUb = idxItv.ub().getIntNumeral();
484  }
485  }
486  // for pointer type, flattened index = elemNum * idx
487  if (SVFUtil::isa<SVFPointerType>(type))
488  {
490  idxLb = (double)Options::MaxFieldLimit() / elemNum < idxLb? Options::MaxFieldLimit(): idxLb * elemNum;
491  idxUb = (double)Options::MaxFieldLimit() / elemNum < idxUb? Options::MaxFieldLimit(): idxUb * elemNum;
492  }
493  // for array or struct, get flattened index from SymbolTable Info
494  else
495  {
497  {
498  const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()
499  ->getTypeInfo(type)
501  if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
502  {
503  idxLb = idxUb = 0;
504  }
505  else
506  {
508  type, idxLb);
510  type, idxUb);
511  }
512  }
513  else
514  idxLb = idxUb = 0;
515  }
516  res = res + IntervalValue(idxLb, idxUb);
517  }
519  if (res.isBottom())
520  {
521  res = IntervalValue(0);
522  }
523  return res;
524 }
525 
526 
528 {
529  NodeID varId = var->getId();
530  if (var->hasValue())
531  {
532  const MemObj *obj = var->getMemObj();
534  if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
535  {
536  if (const SVFConstantInt *consInt = SVFUtil::dyn_cast<SVFConstantInt>(obj->getValue()))
537  {
538  s64_t numeral = consInt->getSExtValue();
539  as[varId] = IntervalValue(numeral, numeral);
540  }
541  else if (const SVFConstantFP* consFP = SVFUtil::dyn_cast<SVFConstantFP>(obj->getValue()))
542  as[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
543  else if (SVFUtil::isa<SVFConstantNullPtr>(obj->getValue()))
544  as[varId] = IntervalValue(0, 0);
545  else if (SVFUtil::isa<SVFGlobalValue>(obj->getValue()))
546  {
547  as[varId] = AddressValue(getVirtualMemAddress(varId));
548  }
549 
550  else if (obj->isConstantArray() || obj->isConstantStruct())
551  as[varId] = IntervalValue::top();
552  else
553  as[varId] = IntervalValue::top();
554  }
555  else
556  as[varId] = AddressValue(getVirtualMemAddress(varId));
557  }
558  else
559  as[varId] = AddressValue(getVirtualMemAddress(varId));
560 }
561 
562 
564 {
565  initObjVar(as, SVFUtil::cast<ObjVar>(addr->getRHSVar()));
566  if (addr->getRHSVar()->getType()->getKind() == SVFType::SVFIntegerTy)
567  as[addr->getRHSVarID()].getInterval().meet_with(getRangeLimitFromType(addr->getRHSVar()->getType()));
568  as[addr->getLHSVarID()] = as[addr->getRHSVarID()];
569 }
570 
571 
573 {
574  u32_t op0 = binary->getOpVarID(0);
575  u32_t op1 = binary->getOpVarID(1);
576  u32_t res = binary->getResID();
577  if (!inVarToValTable(as, op0)) as[op0] = IntervalValue::top();
578  if (!inVarToValTable(as, op1)) as[op1] = IntervalValue::top();
579  IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
580  IntervalValue resVal;
581  switch (binary->getOpcode())
582  {
583  case BinaryOPStmt::Add:
584  case BinaryOPStmt::FAdd:
585  resVal = (lhs + rhs);
586  break;
587  case BinaryOPStmt::Sub:
588  case BinaryOPStmt::FSub:
589  resVal = (lhs - rhs);
590  break;
591  case BinaryOPStmt::Mul:
592  case BinaryOPStmt::FMul:
593  resVal = (lhs * rhs);
594  break;
595  case BinaryOPStmt::SDiv:
596  case BinaryOPStmt::FDiv:
597  case BinaryOPStmt::UDiv:
598  resVal = (lhs / rhs);
599  break;
600  case BinaryOPStmt::SRem:
601  case BinaryOPStmt::FRem:
602  case BinaryOPStmt::URem:
603  resVal = (lhs % rhs);
604  break;
605  case BinaryOPStmt::Xor:
606  resVal = (lhs ^ rhs);
607  break;
608  case BinaryOPStmt::And:
609  resVal = (lhs & rhs);
610  break;
611  case BinaryOPStmt::Or:
612  resVal = (lhs | rhs);
613  break;
614  case BinaryOPStmt::AShr:
615  resVal = (lhs >> rhs);
616  break;
617  case BinaryOPStmt::Shl:
618  resVal = (lhs << rhs);
619  break;
620  case BinaryOPStmt::LShr:
621  resVal = (lhs >> rhs);
622  break;
623  default:
624  assert(false && "undefined binary: ");
625  }
626  as[res] = resVal;
627 }
628 
630 {
631  u32_t op0 = cmp->getOpVarID(0);
632  u32_t op1 = cmp->getOpVarID(1);
633  if (!inVarToValTable(as, op0)) as[op0] = IntervalValue::top();
634  if (!inVarToValTable(as, op1)) as[op1] = IntervalValue::top();
635  u32_t res = cmp->getResID();
636  if (inVarToValTable(as, op0) && inVarToValTable(as, op1))
637  {
638  IntervalValue resVal;
639  IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
640  //AbstractValue
641  auto predicate = cmp->getPredicate();
642  switch (predicate)
643  {
644  case CmpStmt::ICMP_EQ:
645  case CmpStmt::FCMP_OEQ:
646  case CmpStmt::FCMP_UEQ:
647  resVal = (lhs == rhs);
648  // resVal = (lhs.getInterval() == rhs.getInterval());
649  break;
650  case CmpStmt::ICMP_NE:
651  case CmpStmt::FCMP_ONE:
652  case CmpStmt::FCMP_UNE:
653  resVal = (lhs != rhs);
654  break;
655  case CmpStmt::ICMP_UGT:
656  case CmpStmt::ICMP_SGT:
657  case CmpStmt::FCMP_OGT:
658  case CmpStmt::FCMP_UGT:
659  resVal = (lhs > rhs);
660  break;
661  case CmpStmt::ICMP_UGE:
662  case CmpStmt::ICMP_SGE:
663  case CmpStmt::FCMP_OGE:
664  case CmpStmt::FCMP_UGE:
665  resVal = (lhs >= rhs);
666  break;
667  case CmpStmt::ICMP_ULT:
668  case CmpStmt::ICMP_SLT:
669  case CmpStmt::FCMP_OLT:
670  case CmpStmt::FCMP_ULT:
671  resVal = (lhs < rhs);
672  break;
673  case CmpStmt::ICMP_ULE:
674  case CmpStmt::ICMP_SLE:
675  case CmpStmt::FCMP_OLE:
676  case CmpStmt::FCMP_ULE:
677  resVal = (lhs <= rhs);
678  break;
679  case CmpStmt::FCMP_FALSE:
680  resVal = IntervalValue(0, 0);
681  break;
682  case CmpStmt::FCMP_TRUE:
683  resVal = IntervalValue(1, 1);
684  break;
685  default:
686  {
687  assert(false && "undefined compare: ");
688  }
689  }
690  as[res] = resVal;
691  }
692  else if (inVarToAddrsTable(as, op0) && inVarToAddrsTable(as, op1))
693  {
694  IntervalValue resVal;
695  AbstractValue &lhs = getAddrs(as, op0), &rhs = getAddrs(as, op1);
696  auto predicate = cmp->getPredicate();
697  switch (predicate)
698  {
699  case CmpStmt::ICMP_EQ:
700  case CmpStmt::FCMP_OEQ:
701  case CmpStmt::FCMP_UEQ:
702  {
703  if (lhs.getAddrs().hasIntersect(rhs.getAddrs()))
704  {
705  resVal = IntervalValue(0, 1);
706  }
707  else if (lhs.getAddrs().empty() && rhs.getAddrs().empty())
708  {
709  resVal = IntervalValue(1, 1);
710  }
711  else
712  {
713  resVal = IntervalValue(0, 0);
714  }
715  break;
716  }
717  case CmpStmt::ICMP_NE:
718  case CmpStmt::FCMP_ONE:
719  case CmpStmt::FCMP_UNE:
720  {
721  if (lhs.getAddrs().hasIntersect(rhs.getAddrs()))
722  {
723  resVal = IntervalValue(0, 1);
724  }
725  else if (lhs.getAddrs().empty() && rhs.getAddrs().empty())
726  {
727  resVal = IntervalValue(0, 0);
728  }
729  else
730  {
731  resVal = IntervalValue(1, 1);
732  }
733  break;
734  }
735  case CmpStmt::ICMP_UGT:
736  case CmpStmt::ICMP_SGT:
737  case CmpStmt::FCMP_OGT:
738  case CmpStmt::FCMP_UGT:
739  {
740  if (lhs.getAddrs().size() == 1 && rhs.getAddrs().size() == 1)
741  {
742  resVal = IntervalValue(*lhs.getAddrs().begin() > *rhs.getAddrs().begin());
743  }
744  else
745  {
746  resVal = IntervalValue(0, 1);
747  }
748  break;
749  }
750  case CmpStmt::ICMP_UGE:
751  case CmpStmt::ICMP_SGE:
752  case CmpStmt::FCMP_OGE:
753  case CmpStmt::FCMP_UGE:
754  {
755  if (lhs.getAddrs().size() == 1 && rhs.getAddrs().size() == 1)
756  {
757  resVal = IntervalValue(*lhs.getAddrs().begin() >= *rhs.getAddrs().begin());
758  }
759  else
760  {
761  resVal = IntervalValue(0, 1);
762  }
763  break;
764  }
765  case CmpStmt::ICMP_ULT:
766  case CmpStmt::ICMP_SLT:
767  case CmpStmt::FCMP_OLT:
768  case CmpStmt::FCMP_ULT:
769  {
770  if (lhs.getAddrs().size() == 1 && rhs.getAddrs().size() == 1)
771  {
772  resVal = IntervalValue(*lhs.getAddrs().begin() < *rhs.getAddrs().begin());
773  }
774  else
775  {
776  resVal = IntervalValue(0, 1);
777  }
778  break;
779  }
780  case CmpStmt::ICMP_ULE:
781  case CmpStmt::ICMP_SLE:
782  case CmpStmt::FCMP_OLE:
783  case CmpStmt::FCMP_ULE:
784  {
785  if (lhs.getAddrs().size() == 1 && rhs.getAddrs().size() == 1)
786  {
787  resVal = IntervalValue(*lhs.getAddrs().begin() <= *rhs.getAddrs().begin());
788  }
789  else
790  {
791  resVal = IntervalValue(0, 1);
792  }
793  break;
794  }
795  case CmpStmt::FCMP_FALSE:
796  resVal = IntervalValue(0, 0);
797  break;
798  case CmpStmt::FCMP_TRUE:
799  resVal = IntervalValue(1, 1);
800  break;
801  default:
802  {
803  assert(false && "undefined compare: ");
804  }
805  }
806  as[res] = resVal;
807  }
808 }
809 
811 {
812  u32_t rhs = load->getRHSVarID();
813  u32_t lhs = load->getLHSVarID();
814  AbstractValue &addrs = as[rhs];
815  AbstractValue rhsVal; // interval::bottom Address::bottom
816  // AbstractValue absRhs
817  for (const auto &addr: addrs.getAddrs())
818  rhsVal.join_with(as.load(addr));
819  as[lhs] = rhsVal;
820 }
821 
823 {
824  u32_t rhs = store->getRHSVarID();
825  u32_t lhs = store->getLHSVarID();
826 
827  for (const auto &addr: as[lhs].getAddrs())
828  {
829  as.store(addr, as[rhs]);
830  }
831 }
832 
834 {
835  u32_t lhs = copy->getLHSVarID();
836  u32_t rhs = copy->getRHSVarID();
837 
838  if (copy->getCopyKind() == CopyStmt::COPYVAL)
839  {
840  as[lhs] = as[rhs];
841  }
842  else if (copy->getCopyKind() == CopyStmt::ZEXT)
843  {
844  as[lhs] = getZExtValue(as, copy->getRHSVar());
845  }
846  else if (copy->getCopyKind() == CopyStmt::SEXT)
847  {
848  as[lhs] = getSExtValue(as, copy->getRHSVar());
849  }
850  else if (copy->getCopyKind() == CopyStmt::FPTOSI)
851  {
852  as[lhs] = getFPToSIntValue(as, copy->getRHSVar());
853  }
854  else if (copy->getCopyKind() == CopyStmt::FPTOUI)
855  {
856  as[lhs] = getFPToUIntValue(as, copy->getRHSVar());
857  }
858  else if (copy->getCopyKind() == CopyStmt::SITOFP)
859  {
860  as[lhs] = getSIntToFPValue(as, copy->getRHSVar());
861  }
862  else if (copy->getCopyKind() == CopyStmt::UITOFP)
863  {
864  as[lhs] = getUIntToFPValue(as, copy->getRHSVar());
865  }
866  else if (copy->getCopyKind() == CopyStmt::TRUNC)
867  {
868  as[lhs] = getTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
869  }
870  else if (copy->getCopyKind() == CopyStmt::FPTRUNC)
871  {
872  as[lhs] = getFPTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
873  }
874  else if (copy->getCopyKind() == CopyStmt::INTTOPTR)
875  {
876  //insert nullptr
877  }
878  else if (copy->getCopyKind() == CopyStmt::PTRTOINT)
879  {
880  as[lhs] = IntervalValue::top();
881  }
882  else if (copy->getCopyKind() == CopyStmt::BITCAST)
883  {
884  if (as[rhs].isAddr())
885  {
886  as[lhs] = as[rhs];
887  }
888  else
889  {
890  // do nothing
891  }
892  }
893  else
894  {
895  assert(false && "undefined copy kind");
896  abort();
897  }
898 }
899 
901 {
902  u32_t rhs = gep->getRHSVarID();
903  u32_t lhs = gep->getLHSVarID();
904  IntervalValue offsetPair = getElementIndex(as, gep);
905  AbstractValue gepAddrs;
906  APOffset lb = offsetPair.lb().getIntNumeral() < Options::MaxFieldLimit()?
907  offsetPair.lb().getIntNumeral(): Options::MaxFieldLimit();
908  APOffset ub = offsetPair.ub().getIntNumeral() < Options::MaxFieldLimit()?
909  offsetPair.ub().getIntNumeral(): Options::MaxFieldLimit();
910  for (APOffset i = lb; i <= ub; i++)
911  gepAddrs.join_with(getGepObjAddress(as, rhs, i));
912  as[lhs] = gepAddrs;
913 }
914 
916 {
917  u32_t res = select->getResID();
918  u32_t tval = select->getTrueValue()->getId();
919  u32_t fval = select->getFalseValue()->getId();
920  u32_t cond = select->getCondition()->getId();
921  if (as[cond].getInterval().is_numeral())
922  {
923  as[res] = as[cond].getInterval().is_zero() ? as[fval] : as[tval];
924  }
925  else
926  {
927  as[res] = as[tval];
928  as[res].join_with(as[fval]);
929  }
930 }
931 
933 {
934  u32_t res = phi->getResID();
935  AbstractValue rhs;
936  for (u32_t i = 0; i < phi->getOpVarNum(); i++)
937  {
938  NodeID curId = phi->getOpVarID(i);
939  rhs.join_with(as[curId]);
940  }
941  as[res] = rhs;
942 }
943 
944 
946 {
947  NodeID lhs = callPE->getLHSVarID();
948  NodeID rhs = callPE->getRHSVarID();
949  as[lhs] = as[rhs];
950 }
951 
953 {
954  NodeID lhs = retPE->getLHSVarID();
955  NodeID rhs = retPE->getRHSVarID();
956  as[lhs] = as[rhs];
957 }
newitem type
Definition: cJSON.cpp:2739
copy
Definition: cJSON.cpp:414
buffer offset
Definition: cJSON.cpp:1113
void store(u32_t addr, const AbstractValue &val)
VarToAbsValMap _varToAbsVal
Map a variable (symbol) to its abstract value.
AddrToAbsValMap _addrToAbsVal
Map a memory address to its stored abstract value.
virtual AbstractValue & load(u32_t addr)
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
Definition: AbstractState.h:84
void join_with(const AbstractValue &other)
AddressValue & getAddrs()
u32_t getElementNum(const SVFType *type) const
Return element number of a type.
Definition: AccessPath.cpp:63
std::pair< const SVFVar *, const SVFType * > IdxOperandPair
Definition: AccessPath.h:64
const SVFType * gepSrcPointeeType() const
Definition: AccessPath.h:112
bool hasIntersect(const AddressValue &other)
Definition: AddressValue.h:164
std::pair< AddressValue::AddrSet::iterator, bool > insert(u32_t id)
Definition: AddressValue.h:112
bool empty() const
Definition: AddressValue.h:102
u32_t size() const
Definition: AddressValue.h:107
AddrSet::const_iterator begin() const
Definition: AddressValue.h:92
NodeID getRHSVarID() const
NodeID getLHSVarID() const
SVFVar * getRHSVar() const
u32_t getOpcode() const
s64_t getIntNumeral() const
Definition: NumericValue.h:703
u32_t getPredicate() const
@ ICMP_SGT
signed greater than
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_UGE
unsigned greater or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_NE
not equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_ULT
unsigned less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ ICMP_SLT
signed less than
@ ICMP_UGT
unsigned greater than
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
NodeID getId() const
Get ID.
Definition: GenericGraph.h:180
APOffset accumulateConstantOffset() const
Return accumulated constant offset (when accessing array or struct) if this offset is a constant.
const AccessPath::IdxOperandPairs getOffsetVarAndGepTypePairVec() const
const AccessPath & getAccessPath() const
bool isConstantOffset() const
Return TRUE if this is a constant location set.
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
const BoundedInt & lb() const
Return the lower bound.
bool isBottom() const
Definition: IntervalValue.h:71
const BoundedInt & ub() const
Return the upper bound.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
Definition: IntervalValue.h:94
bool isConstantStruct() const
bool isConstDataOrConstGlobal() const
const SVFValue * getValue() const
Get the reference value to this object.
bool isConstantArray() const
NodeID getOpVarID(u32_t pos) const
NodeID getResID() const
u32_t getOpVarNum() const
const MemObj * getMemObj() const
Return memory object.
Definition: SVFVariables.h:353
static const Option< bool > ModelArrays
Definition: Options.h:207
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition: Options.h:38
void handleSelect(AbstractState &es, const SelectStmt *select)
void handlePhi(AbstractState &es, const PhiStmt *phi)
IntervalValue getRangeLimitFromType(const SVFType *type)
Return the value range of Integer SVF Type, e.g. unsigned i8 Type->[0, 255], signed i8 Type->[-128,...
IntervalValue getFPTruncValue(const AbstractState &es, const SVFVar *var, const SVFType *dstType)
void handleLoad(AbstractState &es, const LoadStmt *load)
IntervalValue getFPToUIntValue(const AbstractState &es, const SVFVar *var)
static AbstractValue globalNulladdrs
void narrowAddrs(AbstractState &es, AbstractState &lhs, const AbstractState &rhs)
void initObjVar(AbstractState &as, const ObjVar *var)
Init ObjVar.
IntervalValue getByteOffset(const AbstractState &es, const GepStmt *gep)
void handleCmp(AbstractState &es, const CmpStmt *cmp)
void handleGep(AbstractState &es, const GepStmt *gep)
void handleStore(AbstractState &es, const StoreStmt *store)
AddressValue getGepObjAddress(AbstractState &es, u32_t pointer, APOffset offset)
Return the field address given a pointer points to a struct object and an offset.
IntervalValue getUIntToFPValue(const AbstractState &es, const SVFVar *var)
IntervalValue getZExtValue(const AbstractState &es, const SVFVar *var)
void handleRet(AbstractState &es, const RetPE *retPE)
IntervalValue getElementIndex(const AbstractState &es, const GepStmt *gep)
Return the offset expression of a GepStmt.
IntervalValue getFPToSIntValue(const AbstractState &es, const SVFVar *var)
void handleBinary(AbstractState &es, const BinaryOPStmt *binary)
IntervalValue getSExtValue(const AbstractState &es, const SVFVar *var)
IntervalValue getSIntToFPValue(const AbstractState &es, const SVFVar *var)
void handleCopy(AbstractState &es, const CopyStmt *copy)
void handleCall(AbstractState &es, const CallPE *callPE)
void widenAddrs(AbstractState &es, AbstractState &lhs, const AbstractState &rhs)
IntervalValue getTruncValue(const AbstractState &es, const SVFVar *var, const SVFType *dstType)
void handleAddr(AbstractState &es, const AddrStmt *addr)
@ SVFIntegerTy
Definition: SVFType.h:169
GNodeK getKind() const
Definition: SVFType.h:213
u32_t getByteSize() const
Definition: SVFType.h:244
bool hasValue() const
Definition: SVFVariables.h:112
virtual const SVFType * getType() const
Return type of the value.
Definition: SVFVariables.h:107
const SVFVar * getTrueValue() const
const SVFVar * getCondition() const
const SVFVar * getFalseValue() const
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition: SVFType.h:98
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
static SymbolTableInfo * SymbolInfo()
Singleton design here to make sure we only have one instance during any analysis.
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
for isBitcode
Definition: BasicTypes.h:68
unsigned NodeID
s64_t APOffset
Definition: GeneralType.h:60
signed short s16_t
Definition: GeneralType.h:53
unsigned short u16_t
Definition: GeneralType.h:52
signed s32_t
Definition: GeneralType.h:47
unsigned u32_t
Definition: GeneralType.h:46
signed long long s64_t
Definition: GeneralType.h:49