Static Value-Flow Analysis
Loading...
Searching...
No Matches
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.
 
void initExtFunMap ()
 Initializes the external function map.
 
std::string strRead (AbstractState &as, const SVFVar *rhs)
 Reads a string from the abstract state.
 
void handleExtAPI (const CallICFGNode *call)
 Handles an external API call.
 
void handleStrcpy (const CallICFGNode *call)
 Handles the strcpy API call.
 
IntervalValue getStrlen (AbstractState &as, const SVF::SVFVar *strValue)
 Calculates the length of a string.
 
void handleStrcat (const SVF::CallICFGNode *call)
 Handles the strcat API call.
 
void handleMemcpy (AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
 Handles the memcpy API call.
 
void handleMemset (AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
 Handles the memset API call.
 
IntervalValue getRangeLimitFromType (const SVFType *type)
 Gets the range limit from a type.
 
AbstractStategetAbsStateFromTrace (const ICFGNode *node)
 Retrieves the abstract state from the trace for a given ICFG node.
 
const SVFVargetSVFVar (const SVFValue *val)
 Retrieves the SVF variable from a given SVF value.
 

Protected Attributes

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

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.

32{
34 icfg = svfir->getICFG();
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
ICFG * getICFG() const
Definition SVFIR.h:172
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

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 343 of file AbsExtAPI.cpp.

344{
345 const ICFGNode* repNode = icfg->getRepNode(node);
346 if (abstractTrace.count(repNode) == 0)
347 {
348 assert(0 && "No preAbsTrace for this node");
349 }
350 else
351 {
352 return abstractTrace[repNode];
353 }
354}
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 700 of file AbsExtAPI.cpp.

701{
702 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
703 {
704 u32_t bits = type->getByteSize() * 8;
705 s64_t ub = 0;
706 s64_t lb = 0;
707 if (bits >= 32)
708 {
709 if (intType->isSigned())
710 {
711 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
712 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
713 }
714 else
715 {
716 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
717 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
718 }
719 }
720 else if (bits == 16)
721 {
722 if (intType->isSigned())
723 {
724 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
725 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
726 }
727 else
728 {
729 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
730 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
731 }
732 }
733 else if (bits == 8)
734 {
735 if (intType->isSigned())
736 {
737 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
738 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
739 }
740 else
741 {
742 ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
743 lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
744 }
745 }
746 return IntervalValue(lb, ub);
747 }
748 else if (SVFUtil::isa<SVFOtherType>(type))
749 {
750 // handle other type like float double, set s32_t as the range
751 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
752 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
753 return IntervalValue(lb, ub);
754 }
755 else
756 {
757 return IntervalValue::top();
758 // other types, return top interval
759 }
760}
unsigned u32_t
Definition CommandLine.h:18
newitem type
Definition cJSON.cpp:2739
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
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 468 of file AbsExtAPI.cpp.

469{
470 NodeID value_id = strValue->getId();
471 u32_t dst_size = 0;
472 for (const auto& addr : as[value_id].getAddrs())
473 {
476 {
478 }
479 else
480 {
481 const ICFGNode* icfgNode = SVFUtil::cast<ICFGNode>( svfir->getBaseObj(objId)->getGNode());
482 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
483 {
484 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
485 {
486 dst_size = as.getAllocaInstByteSize(addrStmt);
487 }
488 }
489 }
490 }
491 u32_t len = 0;
492 u32_t elemSize = 1;
493 if (as.inVarToAddrsTable(value_id))
494 {
495 for (u32_t index = 0; index < dst_size; index++)
496 {
498 as.getGepObjAddrs(value_id, IntervalValue(index));
500 for (const auto &addr: expr0.getAddrs())
501 {
502 val.join_with(as.load(addr));
503 }
504 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
505 {
506 break;
507 }
508 ++len;
509 }
510 if (strValue->getType()->isArrayTy())
511 {
512 elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
513 }
514 else if (strValue->getType()->isPointerTy())
515 {
516 if (const SVFType* elemType = as.getPointeeElement(value_id))
517 {
518 if (elemType->isArrayTy())
519 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
520 else
521 elemSize = elemType->getByteSize();
522 }
523 else
524 {
525 elemSize = 1;
526 }
527 }
528 else
529 {
530 assert(false && "we cannot support this type");
531 }
532 }
533 if (len == 0)
534 {
536 }
537 else
538 {
539 return IntervalValue(len * elemSize);
540 }
541}
int index
Definition cJSON.h:170
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
void join_with(const AbstractValue &other)
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 MemObj * getBaseObj(NodeID id) const
Definition SVFIR.h:481
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 762 of file AbsExtAPI.cpp.

763{
766}
bool hasGNode(NodeID id) const
Has a node.
NodeType * getGNode(NodeID id) const
Get a node.
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 386 of file AbsExtAPI.cpp.

387{
389 const SVFFunction *fun = call->getCalledFunction();
390 assert(fun && "SVFFunction* is nullptr");
392 // get type of mem api
393 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
394 {
395 if (annotation.find("MEMCPY") != std::string::npos)
396 extType = MEMCPY;
397 if (annotation.find("MEMSET") != std::string::npos)
398 extType = MEMSET;
399 if (annotation.find("STRCPY") != std::string::npos)
400 extType = STRCPY;
401 if (annotation.find("STRCAT") != std::string::npos)
402 extType = STRCAT;
403 }
404 if (extType == UNCLASSIFIED)
405 {
406 if (func_map.find(fun->getName()) != func_map.end())
407 {
408 func_map[fun->getName()](call);
409 }
410 else
411 {
412 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
413 {
414 u32_t lhsId = ret->getId();
415 if (as.inVarToAddrsTable(lhsId))
416 {
417
418 }
419 else
420 {
422 }
423 }
424 return;
425 }
426 }
427 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
428 else if (extType == MEMCPY)
429 {
430 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
431 svfir->getGNode(call->getArgument(0)->getId());
432 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
433 }
434 else if (extType == MEMSET)
435 {
436 // memset dst is arg0, elem is arg1, size is arg2
437 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
438 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
439 handleMemset(as, call->getArgument(0), elem, len);
440 }
441 else if (extType == STRCPY)
442 {
443 handleStrcpy(call);
444 }
445 else if (extType == STRCAT)
446 {
447 handleStrcat(call);
448 }
449 else
450 {
451
452 }
453 return;
454}
void handleMemset(AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
Handles the memset API call.
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
void handleMemcpy(AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
Handles the memcpy API call.
void handleStrcat(const SVF::CallICFGNode *call)
Handles the strcat API call.
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:52
void handleStrcpy(const CallICFGNode *call)
Handles the strcpy API call.
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
Definition AbsExtAPI.h:144
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:500
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:457
const SVFFunction * getCalledFunction() const
Definition ICFGNode.h:518
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:627
NodeID getId() const
Get ID.
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 579 of file AbsExtAPI.cpp.

580{
581 u32_t dstId = dst->getId(); // pts(dstId) = {objid} objbar objtypeinfo->getType().
582 u32_t srcId = src->getId();
583 u32_t elemSize = 1;
584 if (dst->getType()->isArrayTy())
585 {
586 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
587 }
588 // memcpy(i32*, i32*, 40)
589 else if (dst->getType()->isPointerTy())
590 {
591 if (const SVFType* elemType = as.getPointeeElement(dstId))
592 {
593 if (elemType->isArrayTy())
594 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
595 else
596 elemSize = elemType->getByteSize();
597 }
598 else
599 {
600 elemSize = 1;
601 }
602 }
603 else
604 {
605 assert(false && "we cannot support this type");
606 }
607 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
608 u32_t range_val = size / elemSize;
609 if (as.inVarToAddrsTable(srcId) && as.inVarToAddrsTable(dstId))
610 {
611 for (u32_t index = 0; index < range_val; index++)
612 {
613 // dead loop for string and break if there's a \0. If no \0, it will throw err.
615 as.getGepObjAddrs(srcId, IntervalValue(index));
617 as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
618 for (const auto &dst: expr_dst.getAddrs())
619 {
620 for (const auto &src: expr_src.getAddrs())
621 {
623 if (as.inAddrToValTable(objId))
624 {
625 as.store(dst, as.load(src));
626 }
627 else if (as.inAddrToAddrsTable(objId))
628 {
629 as.store(dst, as.load(src));
630 }
631 }
632 }
633 }
634 }
635}
bool isArrayTy() const
Definition SVFType.h:254
bool isPointerTy() const
Definition SVFType.h:249
virtual const SVFType * getType() const
Return type of the value.

◆ 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 637 of file AbsExtAPI.cpp.

638{
639 u32_t dstId = dst->getId();
640 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
641 u32_t elemSize = 1;
642 if (dst->getType()->isArrayTy())
643 {
644 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
645 }
646 else if (dst->getType()->isPointerTy())
647 {
648 if (const SVFType* elemType = as.getPointeeElement(dstId))
649 {
650 elemSize = elemType->getByteSize();
651 }
652 else
653 {
654 elemSize = 1;
655 }
656 }
657 else
658 {
659 assert(false && "we cannot support this type");
660 }
661
662 u32_t range_val = size / elemSize;
663 for (u32_t index = 0; index < range_val; index++)
664 {
665 // dead loop for string and break if there's a \0. If no \0, it will throw err.
666 if (as.inVarToAddrsTable(dstId))
667 {
668 AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
669 for (const auto &addr: lhs_gep.getAddrs())
670 {
672 if (as.inAddrToValTable(objId))
673 {
674 AbstractValue tmp = as.load(addr);
676 as.store(addr, tmp);
677 }
678 else
679 {
680 as.store(addr, elem);
681 }
682 }
683 }
684 else
685 break;
686 }
687}

◆ handleStrcat()

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

Handles the strcat API call.

Parameters
callPointer to the call ICFG node.

Definition at line 544 of file AbsExtAPI.cpp.

545{
546 // __strcat_chk, strcat, __wcscat_chk, wcscat, __strncat_chk, strncat, __wcsncat_chk, wcsncat
547 // to check it is strcat group or strncat group
549 const SVFFunction *fun = call->getCalledFunction();
550 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
551 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
552 if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
553 {
554 const SVFVar* arg0Val = call->getArgument(0);
555 const SVFVar* arg1Val = call->getArgument(1);
559 handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
560 // do memcpy
561 }
562 else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
563 {
564 const SVFVar* arg0Val = call->getArgument(0);
565 const SVFVar* arg1Val = call->getArgument(1);
566 const SVFVar* arg2Val = call->getArgument(2);
567 IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
570 handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
571 // do memcpy
572 }
573 else
574 {
575 assert(false && "unknown strcat function, please add it to strcatGroup or strncatGroup");
576 }
577}
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.

◆ handleStrcpy()

void AbsExtAPI::handleStrcpy ( const CallICFGNode call)

Handles the strcpy API call.

Parameters
callPointer to the call ICFG node.

Definition at line 456 of file AbsExtAPI.cpp.

457{
458 // strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
459 // get the dst and src
461 const SVFVar* arg0Val = call->getArgument(0);
462 const SVFVar* arg1Val = call->getArgument(1);
464 // no need to -1, since it has \0 as the last byte
465 handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
466}

◆ 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);
72
73 auto sse_svf_assert = [this](const CallICFGNode* callNode)
74 {
76 u32_t arg0 = callNode->getArgument(0)->getId();
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();
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;
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;
127 AbstractValue& num = as[callNode->getArgument(0)->getId()];
128 AbstractValue& lb = as[callNode->getArgument(1)->getId()];
129 AbstractValue& ub = as[callNode->getArgument(2)->getId()];
131 num.getInterval().set_to_top();
132 num.getInterval().meet_with(IntervalValue(lb.getInterval().lb(), ub.getInterval().ub()));
133 const ICFGNode* node = SVFUtil::cast<ValVar>(callNode->getArgument(0))->getICFGNode();
134 for (const SVFStmt* stmt: node->getSVFStmts())
135 {
136 if (SVFUtil::isa<LoadStmt>(stmt))
137 {
138 const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
139 NodeID rhsId = load->getRHSVarID();
140 as.storeValue(rhsId, num);
141 }
142 }
143 return;
144 };
145 func_map["set_value"] = svf_set_value;
146
147 auto sse_scanf = [&](const CallICFGNode* callNode)
148 {
150 //scanf("%d", &data);
151 if (callNode->arg_size() < 2) return;
152
153 u32_t dst_id = callNode->getArgument(1)->getId();
154 if (!as.inVarToAddrsTable(dst_id))
155 {
156 return;
157 }
158 else
159 {
161 for (auto vaddr: Addrs.getAddrs())
162 {
165 as.store(vaddr, range);
166 }
167 }
168 };
169 auto sse_fscanf = [&](const CallICFGNode* callNode)
170 {
171 //fscanf(stdin, "%d", &data);
172 if (callNode->arg_size() < 3) return;
174 u32_t dst_id = callNode->getArgument(2)->getId();
175 if (!as.inVarToAddrsTable(dst_id))
176 {
177 }
178 else
179 {
181 for (auto vaddr: Addrs.getAddrs())
182 {
185 as.store(vaddr, range);
186 }
187 }
188 };
189
190 func_map["__isoc99_fscanf"] = sse_fscanf;
191 func_map["__isoc99_scanf"] = sse_scanf;
192 func_map["__isoc99_vscanf"] = sse_scanf;
193 func_map["fscanf"] = sse_fscanf;
194 func_map["scanf"] = sse_scanf;
195 func_map["sscanf"] = sse_scanf;
196 func_map["__isoc99_sscanf"] = sse_scanf;
197 func_map["vscanf"] = sse_scanf;
198
199 auto sse_fread = [&](const CallICFGNode *callNode)
200 {
201 if (callNode->arg_size() < 3) return;
203 u32_t block_count_id = callNode->getArgument(2)->getId();
204 u32_t block_size_id = callNode->getArgument(1)->getId();
206 IntervalValue block_size = as[block_size_id].getInterval();
208 };
209 func_map["fread"] = sse_fread;
210
211 auto sse_sprintf = [&](const CallICFGNode *callNode)
212 {
213 // printf is difficult to predict since it has no byte size arguments
214 };
215
216 auto sse_snprintf = [&](const CallICFGNode *callNode)
217 {
218 if (callNode->arg_size() < 2) return;
220 u32_t size_id = callNode->getArgument(1)->getId();
221 u32_t dst_id = callNode->getArgument(0)->getId();
222 // get elem size of arg2
223 u32_t elemSize = 1;
224 if (callNode->getArgument(2)->getType()->isArrayTy())
225 {
226 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
227 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
228 }
229 else if (callNode->getArgument(2)->getType()->isPointerTy())
230 {
231 elemSize = as.getPointeeElement(callNode->getArgument(2)->getId())->getByteSize();
232 }
233 else
234 {
235 return;
236 // assert(false && "we cannot support this type");
237 }
238 IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
239 if (!as.inVarToAddrsTable(dst_id))
240 {
241 }
242 };
243 func_map["__snprintf_chk"] = sse_snprintf;
244 func_map["__vsprintf_chk"] = sse_sprintf;
245 func_map["__sprintf_chk"] = sse_sprintf;
246 func_map["snprintf"] = sse_snprintf;
247 func_map["sprintf"] = sse_sprintf;
248 func_map["vsprintf"] = sse_sprintf;
249 func_map["vsnprintf"] = sse_snprintf;
250 func_map["__vsnprintf_chk"] = sse_snprintf;
251 func_map["swprintf"] = sse_snprintf;
252 func_map["_snwprintf"] = sse_snprintf;
253
254
255 auto sse_itoa = [&](const CallICFGNode* callNode)
256 {
257 // itoa(num, ch, 10);
258 // num: int, ch: char*, 10 is decimal
259 if (callNode->arg_size() < 3) return;
261 u32_t num_id = callNode->getArgument(0)->getId();
262
263 u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
264 std::string snum = std::to_string(num);
265 };
266 func_map["itoa"] = sse_itoa;
267
268
269 auto sse_strlen = [&](const CallICFGNode *callNode)
270 {
271 // check the arg size
272 if (callNode->arg_size() < 1) return;
273 const SVFVar* strValue = callNode->getArgument(0);
275 NodeID value_id = strValue->getId();
276 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
277 u32_t dst_size = 0;
278 for (const auto& addr : as[value_id].getAddrs())
279 {
282 {
284 }
285 else
286 {
287 const ICFGNode* addrNode = SVFUtil::cast<ICFGNode>(svfir->getBaseObj(objId)->getGNode());
288 for (const SVFStmt* stmt2: addrNode->getSVFStmts())
289 {
290 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
291 {
292 dst_size = as.getAllocaInstByteSize(addrStmt);
293 }
294 }
295 }
296 }
297 u32_t len = 0;
298 NodeID dstid = strValue->getId();
299 if (as.inVarToAddrsTable(dstid))
300 {
301 for (u32_t index = 0; index < dst_size; index++)
302 {
304 as.getGepObjAddrs(dstid, IntervalValue(index));
306 for (const auto &addr: expr0.getAddrs())
307 {
308 val.join_with(as.load(addr));
309 }
310 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
311 {
312 break;
313 }
314 ++len;
315 }
316 }
317 if (len == 0)
318 {
320 }
321 else
322 {
324 }
325 };
326 func_map["strlen"] = sse_strlen;
327 func_map["wcslen"] = sse_strlen;
328
329 auto sse_recv = [&](const CallICFGNode *callNode)
330 {
331 // recv(sockfd, buf, len, flags);
332 if (callNode->arg_size() < 4) return;
334 u32_t len_id = callNode->getArgument(2)->getId();
335 IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
336 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
337 as[lhsId] = len;
338 };
339 func_map["recv"] = sse_recv;
340 func_map["__recv"] = sse_recv;
341};
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(AbstractState &as, const SVFVar *rhs)
Reads a string from the abstract state.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
static AbstractInterpretation & getAEInstance()
Set< const CallICFGNode * > checkpoints
IntervalValue & getInterval()
NodeID getRHSVarID() const
const BoundedInt & ub() const
Return the upper bound.
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
const std::string toString() const
const BoundedInt & lb() const
Return the lower bound.
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:54
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 356 of file AbsExtAPI.cpp.

357{
358 // sse read string nodeID->string
359 std::string str0;
360
362 {
363 // dead loop for string and break if there's a \0. If no \0, it will throw err.
364 if (!as.inVarToAddrsTable(rhs->getId())) continue;
366 as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
367
369 for (const auto &addr: expr0.getAddrs())
370 {
371 val.join_with(as.load(addr));
372 }
373 if (!val.getInterval().is_numeral())
374 {
375 break;
376 }
377 if ((char) val.getInterval().getIntNumeral() == '\0')
378 {
379 break;
380 }
381 str0.push_back((char) val.getInterval().getIntNumeral());
382 }
383 return str0;
384}

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: