Static Value-Flow Analysis
Public Types | Public Member Functions | Protected Attributes | List of all members
SVF::AbsExtAPI Class Reference

Handles external API calls and manages abstract states. More...

#include <AbsExtAPI.h>

Public Types

enum  ExtAPIType {
  UNCLASSIFIED , MEMCPY , MEMSET , STRCPY ,
  STRCAT
}
 Enumeration of external API types. More...
 

Public Member Functions

 AbsExtAPI (Map< const ICFGNode *, AbstractState > &traces)
 Constructor for AbsExtAPI. More...
 
void initExtFunMap ()
 Initializes the external function map. More...
 
std::string strRead (AbstractState &as, const SVFVar *rhs)
 Reads a string from the abstract state. More...
 
void handleExtAPI (const CallICFGNode *call)
 Handles an external API call. More...
 
void handleStrcpy (const CallICFGNode *call)
 Handles the strcpy API call. More...
 
IntervalValue getStrlen (AbstractState &as, const SVF::SVFVar *strValue)
 Calculates the length of a string. More...
 
void handleStrcat (const SVF::CallICFGNode *call)
 Handles the strcat API call. More...
 
void handleMemcpy (AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
 Handles the memcpy API call. More...
 
void handleMemset (AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
 Handles the memset API call. More...
 
IntervalValue getRangeLimitFromType (const SVFType *type)
 Gets the range limit from a type. More...
 
AbstractStategetAbsStateFromTrace (const ICFGNode *node)
 Retrieves the abstract state from the trace for a given ICFG node. More...
 
const SVFVargetSVFVar (const SVFValue *val)
 Retrieves the SVF variable from a given SVF value. More...
 

Protected Attributes

SVFIRsvfir
 Pointer to the SVF intermediate representation. More...
 
ICFGicfg
 Pointer to the interprocedural control flow graph. More...
 
Map< const ICFGNode *, AbstractState > & abstractTrace
 Map of ICFG nodes to abstract states. More...
 
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
 Map of function names to handlers. More...
 

Detailed Description

Handles external API calls and manages abstract states.

Definition at line 45 of file AbsExtAPI.h.

Member Enumeration Documentation

◆ ExtAPIType

Enumeration of external API types.

Enumerator
UNCLASSIFIED 
MEMCPY 
MEMSET 
STRCPY 
STRCAT 

Definition at line 52 of file AbsExtAPI.h.

Constructor & Destructor Documentation

◆ AbsExtAPI()

AbsExtAPI::AbsExtAPI ( Map< const ICFGNode *, AbstractState > &  traces)

Constructor for AbsExtAPI.

Parameters
abstractTraceReference to a map of ICFG nodes to abstract states.

Definition at line 31 of file AbsExtAPI.cpp.

31  : abstractTrace(traces)
32 {
33  svfir = PAG::getPAG();
34  icfg = svfir->getICFG();
35  initExtFunMap();
36 }
void initExtFunMap()
Initializes the external function map.
Definition: AbsExtAPI.cpp:38
Map< const ICFGNode *, AbstractState > & abstractTrace
Map of ICFG nodes to abstract states.
Definition: AbsExtAPI.h:143
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition: AbsExtAPI.h:141
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition: AbsExtAPI.h:142
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

Member Function Documentation

◆ getAbsStateFromTrace()

AbstractState & AbsExtAPI::getAbsStateFromTrace ( const ICFGNode node)

Retrieves the abstract state from the trace for a given ICFG node.

Parameters
nodePointer to the ICFG node.
Returns
Reference to the abstract state.
Exceptions
Assertionif no trace exists for the node.

Definition at line 344 of file AbsExtAPI.cpp.

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 }
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition: ICFG.h:246

◆ getRangeLimitFromType()

IntervalValue AbsExtAPI::getRangeLimitFromType ( const SVFType type)

Gets the range limit from a type.

Parameters
typePointer to the SVF type.
Returns
The interval value representing the range limit.

This function, getRangeLimitFromType, calculates the lower and upper bounds of a numeric range for a given SVFType. It is used to determine the possible value range of integer types. If the type is an SVFIntegerType, it calculates the bounds based on the size and signedness of the type. The calculated bounds are returned as an IntervalValue representing the lower (lb) and upper (ub) limits of the range.

Parameters
typeThe SVFType for which to calculate the value range.
Returns
An IntervalValue representing the lower and upper bounds of the range.

Definition at line 701 of file AbsExtAPI.cpp.

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 }
unsigned u32_t
Definition: CommandLine.h:18
newitem type
Definition: cJSON.cpp:2739
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
Definition: IntervalValue.h:94
signed long long s64_t
Definition: GeneralType.h:49

◆ getStrlen()

IntervalValue AbsExtAPI::getStrlen ( AbstractState as,
const SVF::SVFVar strValue 
)

Calculates the length of a string.

Parameters
asReference to the abstract state.
strValuePointer to the SVF variable representing the string.
Returns
The interval value representing the string length.

Definition at line 469 of file AbsExtAPI.cpp.

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 }
int index
Definition: cJSON.h:170
u32_t getAllocaInstByteSize(const AddrStmt *addr)
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.
AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset)
void join_with(const AbstractValue &other)
AddressValue & getAddrs()
IntervalValue & getInterval()
const SVFStmtList & getSVFStmts() const
Definition: ICFGNode.h:117
s64_t getIntNumeral() const
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
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
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const MemObj * getBaseObj(NodeID id) const
Definition: SVFIR.h:459
bool isArrayTy() const
Definition: SVFType.h:254
bool isPointerTy() const
Definition: SVFType.h:249
virtual const SVFType * getType() const
Return type of the value.
Definition: SVFVariables.h:96
u32_t NodeID
Definition: GeneralType.h:55

◆ getSVFVar()

const SVFVar * AbsExtAPI::getSVFVar ( const SVFValue val)

Retrieves the SVF variable from a given SVF value.

Parameters
valPointer to the SVF value.
Returns
Pointer to the corresponding SVF variable.

Definition at line 763 of file AbsExtAPI.cpp.

764 {
765  assert(svfir->hasGNode(svfir->getValueNode(val)));
766  return svfir->getGNode(svfir->getValueNode(val));
767 }
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
bool hasGNode(NodeID id) const
Has a node.
Definition: GenericGraph.h:661
NodeID getValueNode(const SVFValue *V)
Definition: IRGraph.h:137

◆ handleExtAPI()

void AbsExtAPI::handleExtAPI ( const CallICFGNode call)

Handles an external API call.

Parameters
callPointer to the call ICFG node.

Definition at line 387 of file AbsExtAPI.cpp.

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 }
const char *const string
Definition: cJSON.h:172
void handleMemset(AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
Handles the memset API call.
Definition: AbsExtAPI.cpp:638
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
Definition: AbsExtAPI.cpp:344
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
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
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
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
const SVFVar * getActualRet() const
Return actual return parameter.
Definition: ICFGNode.h:627
const std::string & getName() const
Definition: SVFValue.h:243

◆ handleMemcpy()

void AbsExtAPI::handleMemcpy ( AbstractState as,
const SVF::SVFVar dst,
const SVF::SVFVar src,
IntervalValue  len,
u32_t  start_idx 
)

Handles the memcpy API call.

Parameters
asReference to the abstract state.
dstPointer to the destination SVF variable.
srcPointer to the source SVF variable.
lenThe interval value representing the length to copy.
start_idxThe starting index for copying.

Definition at line 580 of file AbsExtAPI.cpp.

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 }
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
s64_t getIntNumeral() const
Definition: NumericValue.h:703
const BoundedInt & lb() const
Return the lower bound.

◆ handleMemset()

void AbsExtAPI::handleMemset ( AbstractState as,
const SVFVar dst,
IntervalValue  elem,
IntervalValue  len 
)

Handles the memset API call.

Parameters
asReference to the abstract state.
dstPointer to the destination SVF variable.
elemThe interval value representing the element to set.
lenThe interval value representing the length to set.

Definition at line 638 of file AbsExtAPI.cpp.

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 }

◆ handleStrcat()

void AbsExtAPI::handleStrcat ( const SVF::CallICFGNode call)

Handles the strcat API call.

Parameters
callPointer to the call ICFG node.

Definition at line 545 of file AbsExtAPI.cpp.

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 }
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.
Definition: AbsExtAPI.cpp:469

◆ handleStrcpy()

void AbsExtAPI::handleStrcpy ( const CallICFGNode call)

Handles the strcpy API call.

Parameters
callPointer to the call ICFG node.

Definition at line 457 of file AbsExtAPI.cpp.

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 }

◆ initExtFunMap()

void AbsExtAPI::initExtFunMap ( )

Initializes the external function map.

Definition at line 38 of file AbsExtAPI.cpp.

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 };
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(AbstractState &as, const SVFVar *rhs)
Reads a string from the abstract state.
Definition: AbsExtAPI.cpp:357
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
Definition: AbsExtAPI.cpp:701
Set< const CallICFGNode * > checkpoints
static AbstractInterpretation & getAEInstance()
std::string toString() const
virtual bool inVarToValTable(u32_t id) const
whether the variable is in varToVal table
void storeValue(NodeID varId, AbstractValue val)
NodeID getRHSVarID() const
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
const std::string toString() const
const BoundedInt & ub() const
Return the upper bound.
void set_to_top()
Set current IntervalValue as top.
u32_t getByteSize() const
Definition: SVFType.h:244
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
unsigned u32_t
Definition: GeneralType.h:46

◆ strRead()

std::string AbsExtAPI::strRead ( AbstractState as,
const SVFVar rhs 
)

Reads a string from the abstract state.

Parameters
asReference to the abstract state.
rhsPointer to the SVF variable representing the string.
Returns
The string value.

Definition at line 357 of file AbsExtAPI.cpp.

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 }

Member Data Documentation

◆ abstractTrace

Map<const ICFGNode*, AbstractState>& SVF::AbsExtAPI::abstractTrace
protected

Map of ICFG nodes to abstract states.

Definition at line 143 of file AbsExtAPI.h.

◆ func_map

Map<std::string, std::function<void(const CallICFGNode*)> > SVF::AbsExtAPI::func_map
protected

Map of function names to handlers.

Definition at line 144 of file AbsExtAPI.h.

◆ icfg

ICFG* SVF::AbsExtAPI::icfg
protected

Pointer to the interprocedural control flow graph.

Definition at line 142 of file AbsExtAPI.h.

◆ svfir

SVFIR* SVF::AbsExtAPI::svfir
protected

Pointer to the SVF intermediate representation.

Definition at line 141 of file AbsExtAPI.h.


The documentation for this class was generated from the following files: