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.
 

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 43 of file AbsExtAPI.h.

Member Enumeration Documentation

◆ ExtAPIType

Enumeration of external API types.

Enumerator
UNCLASSIFIED 
MEMCPY 
MEMSET 
STRCPY 
STRCAT 

Definition at line 50 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 33 of file AbsExtAPI.cpp.

34{
36 icfg = svfir->getICFG();
38}
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:40
Map< const ICFGNode *, AbstractState > & abstractTrace
Map of ICFG nodes to abstract states.
Definition AbsExtAPI.h:134
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition AbsExtAPI.h:132
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:133
ICFG * getICFG() const
Definition SVFIR.h:163
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 377 of file AbsExtAPI.cpp.

378{
379 const ICFGNode* repNode = icfg->getRepNode(node);
380 if (abstractTrace.count(repNode) == 0)
381 {
382 assert(0 && "No preAbsTrace for this node");
383 }
384 else
385 {
386 return abstractTrace[repNode];
387 }
388}
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 734 of file AbsExtAPI.cpp.

735{
736 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
737 {
738 u32_t bits = type->getByteSize() * 8;
739 s64_t ub = 0;
740 s64_t lb = 0;
741 if (bits >= 32)
742 {
743 if (intType->isSigned())
744 {
745 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
746 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
747 }
748 else
749 {
750 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
751 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
752 }
753 }
754 else if (bits == 16)
755 {
756 if (intType->isSigned())
757 {
758 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
759 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
760 }
761 else
762 {
763 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
764 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
765 }
766 }
767 else if (bits == 8)
768 {
769 if (intType->isSigned())
770 {
771 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
772 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
773 }
774 else
775 {
776 ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
777 lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
778 }
779 }
780 return IntervalValue(lb, ub);
781 }
782 else if (SVFUtil::isa<SVFOtherType>(type))
783 {
784 // handle other type like float double, set s32_t as the range
785 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
786 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
787 return IntervalValue(lb, ub);
788 }
789 else
790 {
791 return IntervalValue::top();
792 // other types, return top interval
793 }
794}
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:50

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

503{
504 NodeID value_id = strValue->getId();
505 u32_t dst_size = 0;
506 for (const auto& addr : as[value_id].getAddrs())
507 {
508 NodeID objId = as.getIDFromAddr(addr);
510 {
512 }
513 else
514 {
515 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
516 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
517 {
518 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
519 {
520 dst_size = as.getAllocaInstByteSize(addrStmt);
521 }
522 }
523 }
524 }
525 u32_t len = 0;
526 u32_t elemSize = 1;
527 if (as.inVarToAddrsTable(value_id))
528 {
529 for (u32_t index = 0; index < dst_size; index++)
530 {
532 as.getGepObjAddrs(value_id, IntervalValue(index));
534 for (const auto &addr: expr0.getAddrs())
535 {
536 val.join_with(as.load(addr));
537 }
538 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
539 {
540 break;
541 }
542 ++len;
543 }
544 if (strValue->getType()->isArrayTy())
545 {
546 elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
547 }
548 else if (strValue->getType()->isPointerTy())
549 {
550 if (const SVFType* elemType = as.getPointeeElement(value_id))
551 {
552 if (elemType->isArrayTy())
553 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
554 else
555 elemSize = elemType->getByteSize();
556 }
557 else
558 {
559 elemSize = 1;
560 }
561 }
562 else
563 {
564 assert(false && "we cannot support this type");
565 }
566 }
567 if (len == 0)
568 {
570 }
571 else
572 {
573 return IntervalValue(len * elemSize);
574 }
575}
int index
Definition cJSON.h:170
void join_with(const AbstractValue &other)
const ICFGNode * getICFGNode() const
Get the ICFGNode related to the creation of this object.
bool isConstantByteSize() const
Check if byte size is a const value.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:39
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:423
u32_t NodeID
Definition GeneralType.h:56

◆ handleExtAPI()

void AbsExtAPI::handleExtAPI ( const CallICFGNode call)

Handles an external API call.

Parameters
callPointer to the call ICFG node.

Definition at line 420 of file AbsExtAPI.cpp.

421{
423 const FunObjVar *fun = call->getCalledFunction();
424 assert(fun && "FunObjVar* is nullptr");
426 // get type of mem api
427 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
428 {
429 if (annotation.find("MEMCPY") != std::string::npos)
430 extType = MEMCPY;
431 if (annotation.find("MEMSET") != std::string::npos)
432 extType = MEMSET;
433 if (annotation.find("STRCPY") != std::string::npos)
434 extType = STRCPY;
435 if (annotation.find("STRCAT") != std::string::npos)
436 extType = STRCAT;
437 }
438 if (extType == UNCLASSIFIED)
439 {
440 if (func_map.find(fun->getName()) != func_map.end())
441 {
442 func_map[fun->getName()](call);
443 }
444 else
445 {
446 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
447 {
448 u32_t lhsId = ret->getId();
449 if (as.inVarToAddrsTable(lhsId))
450 {
451
452 }
453 else
454 {
456 }
457 }
458 return;
459 }
460 }
461 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
462 else if (extType == MEMCPY)
463 {
464 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
465 svfir->getGNode(call->getArgument(0)->getId());
466 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
467 }
468 else if (extType == MEMSET)
469 {
470 // memset dst is arg0, elem is arg1, size is arg2
471 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
472 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
473 handleMemset(as, call->getArgument(0), elem, len);
474 }
475 else if (extType == STRCPY)
476 {
477 handleStrcpy(call);
478 }
479 else if (extType == STRCAT)
480 {
481 handleStrcat(call);
482 }
483 else
484 {
485
486 }
487 return;
488}
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:50
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:135
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:494
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:512
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:451
NodeType * getGNode(NodeID id) const
Get a node.
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:621
NodeID getId() const
Get ID.
Definition SVFValue.h:158
virtual const std::string & getName() const
Definition SVFValue.h:184

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

614{
615 u32_t dstId = dst->getId(); // pts(dstId) = {objid} objbar objtypeinfo->getType().
616 u32_t srcId = src->getId();
617 u32_t elemSize = 1;
618 if (dst->getType()->isArrayTy())
619 {
620 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
621 }
622 // memcpy(i32*, i32*, 40)
623 else if (dst->getType()->isPointerTy())
624 {
625 if (const SVFType* elemType = as.getPointeeElement(dstId))
626 {
627 if (elemType->isArrayTy())
628 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
629 else
630 elemSize = elemType->getByteSize();
631 }
632 else
633 {
634 elemSize = 1;
635 }
636 }
637 else
638 {
639 assert(false && "we cannot support this type");
640 }
641 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
642 u32_t range_val = size / elemSize;
643 if (as.inVarToAddrsTable(srcId) && as.inVarToAddrsTable(dstId))
644 {
645 for (u32_t index = 0; index < range_val; index++)
646 {
647 // dead loop for string and break if there's a \0. If no \0, it will throw err.
649 as.getGepObjAddrs(srcId, IntervalValue(index));
651 as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
652 for (const auto &dst: expr_dst.getAddrs())
653 {
654 for (const auto &src: expr_src.getAddrs())
655 {
656 u32_t objId = as.getIDFromAddr(src);
657 if (as.inAddrToValTable(objId))
658 {
659 as.store(dst, as.load(src));
660 }
661 else if (as.inAddrToAddrsTable(objId))
662 {
663 as.store(dst, as.load(src));
664 }
665 }
666 }
667 }
668 }
669}
bool isArrayTy() const
Definition SVFType.h:254
bool isPointerTy() const
Definition SVFType.h:249
virtual const SVFType * getType() const
Definition SVFValue.h:169

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

672{
673 u32_t dstId = dst->getId();
674 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
675 u32_t elemSize = 1;
676 if (dst->getType()->isArrayTy())
677 {
678 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
679 }
680 else if (dst->getType()->isPointerTy())
681 {
682 if (const SVFType* elemType = as.getPointeeElement(dstId))
683 {
684 elemSize = elemType->getByteSize();
685 }
686 else
687 {
688 elemSize = 1;
689 }
690 }
691 else
692 {
693 assert(false && "we cannot support this type");
694 }
695
696 u32_t range_val = size / elemSize;
697 for (u32_t index = 0; index < range_val; index++)
698 {
699 // dead loop for string and break if there's a \0. If no \0, it will throw err.
700 if (as.inVarToAddrsTable(dstId))
701 {
702 AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
703 for (const auto &addr: lhs_gep.getAddrs())
704 {
705 u32_t objId = as.getIDFromAddr(addr);
706 if (as.inAddrToValTable(objId))
707 {
708 AbstractValue tmp = as.load(addr);
710 as.store(addr, tmp);
711 }
712 else
713 {
714 as.store(addr, elem);
715 }
716 }
717 }
718 else
719 break;
720 }
721}

◆ handleStrcat()

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

Handles the strcat API call.

Parameters
callPointer to the call ICFG node.

Definition at line 578 of file AbsExtAPI.cpp.

579{
580 // __strcat_chk, strcat, __wcscat_chk, wcscat, __strncat_chk, strncat, __wcsncat_chk, wcsncat
581 // to check it is strcat group or strncat group
583 const FunObjVar *fun = call->getCalledFunction();
584 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
585 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
586 if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
587 {
588 const SVFVar* arg0Val = call->getArgument(0);
589 const SVFVar* arg1Val = call->getArgument(1);
593 handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
594 // do memcpy
595 }
596 else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
597 {
598 const SVFVar* arg0Val = call->getArgument(0);
599 const SVFVar* arg1Val = call->getArgument(1);
600 const SVFVar* arg2Val = call->getArgument(2);
601 IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
604 handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
605 // do memcpy
606 }
607 else
608 {
609 assert(false && "unknown strcat function, please add it to strcatGroup or strncatGroup");
610 }
611}
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 490 of file AbsExtAPI.cpp.

491{
492 // strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
493 // get the dst and src
495 const SVFVar* arg0Val = call->getArgument(0);
496 const SVFVar* arg1Val = call->getArgument(1);
498 // no need to -1, since it has \0 as the last byte
499 handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
500}

◆ initExtFunMap()

void AbsExtAPI::initExtFunMap ( )

Initializes the external function map.

Definition at line 40 of file AbsExtAPI.cpp.

41{
42#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
43 auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
44 /* run real ext function */ \
45 AbstractState& as = getAbsStateFromTrace(callNode); \
46 u32_t rhs_id = callNode->getArgument(0)->getId(); \
47 if (!as.inVarToValTable(rhs_id)) return; \
48 u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
49 s32_t res = FUNC_NAME(rhs); \
50 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId(); \
51 as[lhsId] = IntervalValue(res); \
52 return; \
53 }; \
54 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
55
67 SSE_FUNC_PROCESS(llvm.sin.f64, sin);
68 SSE_FUNC_PROCESS(llvm.cos.f64, cos);
69 SSE_FUNC_PROCESS(llvm.tan.f64, tan);
70 SSE_FUNC_PROCESS(llvm.log.f64, log);
74
75 auto sse_svf_assert = [this](const CallICFGNode* callNode)
76 {
78 u32_t arg0 = callNode->getArgument(0)->getId();
80 if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
81 {
82 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
83 }
84 else
85 {
86 SVFUtil::errs() <<"svf_assert Fail. " << callNode->toString() << "\n";
87 assert(false);
88 }
89 return;
90 };
91 func_map["svf_assert"] = sse_svf_assert;
92
93 auto svf_assert_eq = [this](const CallICFGNode* callNode)
94 {
95 u32_t arg0 = callNode->getArgument(0)->getId();
96 u32_t arg1 = callNode->getArgument(1)->getId();
98 if (as[arg0].getInterval().equals(as[arg1].getInterval()))
99 {
100 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
101 }
102 else
103 {
104 SVFUtil::errs() <<"svf_assert_eq Fail. " << callNode->toString() << "\n";
105 assert(false);
106 }
107 return;
108 };
109 func_map["svf_assert_eq"] = svf_assert_eq;
110
111 auto svf_print = [&](const CallICFGNode* callNode)
112 {
113 if (callNode->arg_size() < 2) return;
115 u32_t num_id = callNode->getArgument(0)->getId();
116 std::string text = strRead(as, callNode->getArgument(1));
117 assert(as.inVarToValTable(num_id) && "print() should pass integer");
118 IntervalValue itv = as[num_id].getInterval();
119 std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
120 << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
121 return;
122 };
123 func_map["svf_print"] = svf_print;
124
125 auto svf_set_value = [&](const CallICFGNode* callNode)
126 {
127 if (callNode->arg_size() < 2) return;
129 AbstractValue& num = as[callNode->getArgument(0)->getId()];
130 AbstractValue& lb = as[callNode->getArgument(1)->getId()];
131 AbstractValue& ub = as[callNode->getArgument(2)->getId()];
133 num.getInterval().set_to_top();
134 num.getInterval().meet_with(IntervalValue(lb.getInterval().lb(), ub.getInterval().ub()));
135 const ICFGNode* node = SVFUtil::cast<ValVar>(callNode->getArgument(0))->getICFGNode();
136 for (const SVFStmt* stmt: node->getSVFStmts())
137 {
138 if (SVFUtil::isa<LoadStmt>(stmt))
139 {
140 const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
141 NodeID rhsId = load->getRHSVarID();
142 as.storeValue(rhsId, num);
143 }
144 }
145 return;
146 };
147 func_map["set_value"] = svf_set_value;
148
149 auto sse_scanf = [&](const CallICFGNode* callNode)
150 {
152 //scanf("%d", &data);
153 if (callNode->arg_size() < 2) return;
154
155 u32_t dst_id = callNode->getArgument(1)->getId();
156 if (!as.inVarToAddrsTable(dst_id))
157 {
158 return;
159 }
160 else
161 {
163 for (auto vaddr: Addrs.getAddrs())
164 {
165 u32_t objId = as.getIDFromAddr(vaddr);
167 as.store(vaddr, range);
168 }
169 }
170 };
171 auto sse_fscanf = [&](const CallICFGNode* callNode)
172 {
173 //fscanf(stdin, "%d", &data);
174 if (callNode->arg_size() < 3) return;
176 u32_t dst_id = callNode->getArgument(2)->getId();
177 if (!as.inVarToAddrsTable(dst_id))
178 {
179 }
180 else
181 {
183 for (auto vaddr: Addrs.getAddrs())
184 {
185 u32_t objId = as.getIDFromAddr(vaddr);
187 as.store(vaddr, range);
188 }
189 }
190 };
191
192 func_map["__isoc99_fscanf"] = sse_fscanf;
193 func_map["__isoc99_scanf"] = sse_scanf;
194 func_map["__isoc99_vscanf"] = sse_scanf;
195 func_map["fscanf"] = sse_fscanf;
196 func_map["scanf"] = sse_scanf;
197 func_map["sscanf"] = sse_scanf;
198 func_map["__isoc99_sscanf"] = sse_scanf;
199 func_map["vscanf"] = sse_scanf;
200
201 auto sse_fread = [&](const CallICFGNode *callNode)
202 {
203 if (callNode->arg_size() < 3) return;
205 u32_t block_count_id = callNode->getArgument(2)->getId();
206 u32_t block_size_id = callNode->getArgument(1)->getId();
208 IntervalValue block_size = as[block_size_id].getInterval();
210 };
211 func_map["fread"] = sse_fread;
212
213 auto sse_sprintf = [&](const CallICFGNode *callNode)
214 {
215 // printf is difficult to predict since it has no byte size arguments
216 };
217
218 auto sse_snprintf = [&](const CallICFGNode *callNode)
219 {
220 if (callNode->arg_size() < 2) return;
222 u32_t size_id = callNode->getArgument(1)->getId();
223 u32_t dst_id = callNode->getArgument(0)->getId();
224 // get elem size of arg2
225 u32_t elemSize = 1;
226 if (callNode->getArgument(2)->getType()->isArrayTy())
227 {
228 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
229 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
230 }
231 else if (callNode->getArgument(2)->getType()->isPointerTy())
232 {
233 elemSize = as.getPointeeElement(callNode->getArgument(2)->getId())->getByteSize();
234 }
235 else
236 {
237 return;
238 // assert(false && "we cannot support this type");
239 }
240 IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
241 if (!as.inVarToAddrsTable(dst_id))
242 {
243 }
244 };
245 func_map["__snprintf_chk"] = sse_snprintf;
246 func_map["__vsprintf_chk"] = sse_sprintf;
247 func_map["__sprintf_chk"] = sse_sprintf;
248 func_map["snprintf"] = sse_snprintf;
249 func_map["sprintf"] = sse_sprintf;
250 func_map["vsprintf"] = sse_sprintf;
251 func_map["vsnprintf"] = sse_snprintf;
252 func_map["__vsnprintf_chk"] = sse_snprintf;
253 func_map["swprintf"] = sse_snprintf;
254 func_map["_snwprintf"] = sse_snprintf;
255
256
257 auto sse_itoa = [&](const CallICFGNode* callNode)
258 {
259 // itoa(num, ch, 10);
260 // num: int, ch: char*, 10 is decimal
261 if (callNode->arg_size() < 3) return;
263 u32_t num_id = callNode->getArgument(0)->getId();
264
265 u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
266 std::string snum = std::to_string(num);
267 };
268 func_map["itoa"] = sse_itoa;
269
270
271 auto sse_strlen = [&](const CallICFGNode *callNode)
272 {
273 // check the arg size
274 if (callNode->arg_size() < 1) return;
275 const SVFVar* strValue = callNode->getArgument(0);
277 NodeID value_id = strValue->getId();
278 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
279 u32_t dst_size = 0;
280 for (const auto& addr : as[value_id].getAddrs())
281 {
282 NodeID objId = as.getIDFromAddr(addr);
284 {
286 }
287 else
288 {
290 for (const SVFStmt* stmt2: addrNode->getSVFStmts())
291 {
292 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
293 {
294 dst_size = as.getAllocaInstByteSize(addrStmt);
295 }
296 }
297 }
298 }
299 u32_t len = 0;
301 if (as.inVarToAddrsTable(dstid))
302 {
303 for (u32_t index = 0; index < dst_size; index++)
304 {
306 as.getGepObjAddrs(dstid, IntervalValue(index));
308 for (const auto &addr: expr0.getAddrs())
309 {
310 val.join_with(as.load(addr));
311 }
312 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
313 {
314 break;
315 }
316 ++len;
317 }
318 }
319 if (len == 0)
320 {
322 }
323 else
324 {
326 }
327 };
328 func_map["strlen"] = sse_strlen;
329 func_map["wcslen"] = sse_strlen;
330
331 auto sse_recv = [&](const CallICFGNode *callNode)
332 {
333 // recv(sockfd, buf, len, flags);
334 if (callNode->arg_size() < 4) return;
336 u32_t len_id = callNode->getArgument(2)->getId();
337 IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
338 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
339 as[lhsId] = len;
340 };
341 func_map["recv"] = sse_recv;
342 func_map["__recv"] = sse_recv;
343
344 auto sse_free = [&](const CallICFGNode *callNode)
345 {
346 if (callNode->arg_size() < 1) return;
348 const u32_t freePtr = callNode->getArgument(0)->getId();
349 for (auto addr: as[freePtr].getAddrs())
350 {
352 {
353 // Detected a double free — the address has already been freed.
354 // No action is taken at this point.
355 }
356 else
357 {
358 as.addToFreedAddrs(addr);
359 }
360 }
361 };
362 // Add all free-related functions to func_map
363 std::vector<std::string> freeFunctions =
364 {
365 "VOS_MemFree", "cfree", "free", "free_all_mem", "freeaddrinfo",
366 "gcry_mpi_release", "gcry_sexp_release", "globfree", "nhfree",
367 "obstack_free", "safe_cfree", "safe_free", "safefree", "safexfree",
368 "sm_free", "vim_free", "xfree", "SSL_CTX_free", "SSL_free", "XFree"
369 };
370
371 for (const auto& name : freeFunctions)
372 {
374 }
375};
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
const char *const name
Definition cJSON.h:264
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
static bool isInvalidMem(u32_t addr)
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:932
int isdigit(int c)
Definition extapi.c:937
int isgraph(int c)
Definition extapi.c:942
int isspace(char c)
Definition extapi.c:962
int isprint(int c)
Definition extapi.c:952
int ispunct(int argument)
Definition extapi.c:957
int isblank(int character)
Definition extapi.c:927
int isalnum(int character)
Definition extapi.c:917
int isupper(int c)
Definition extapi.c:967
int isxdigit(int c)
Definition extapi.c:972
int isalpha(int character)
Definition extapi.c:922
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:55
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
unsigned u32_t
Definition GeneralType.h:47

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

391{
392 // sse read string nodeID->string
393 std::string str0;
394
396 {
397 // dead loop for string and break if there's a \0. If no \0, it will throw err.
398 if (!as.inVarToAddrsTable(rhs->getId())) continue;
400 as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
401
403 for (const auto &addr: expr0.getAddrs())
404 {
405 val.join_with(as.load(addr));
406 }
407 if (!val.getInterval().is_numeral())
408 {
409 break;
410 }
411 if ((char) val.getInterval().getIntNumeral() == '\0')
412 {
413 break;
414 }
415 str0.push_back((char) val.getInterval().getIntNumeral());
416 }
417 return str0;
418}

Member Data Documentation

◆ abstractTrace

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

Map of ICFG nodes to abstract states.

Definition at line 134 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 135 of file AbsExtAPI.h.

◆ icfg

ICFG* SVF::AbsExtAPI::icfg
protected

Pointer to the interprocedural control flow graph.

Definition at line 133 of file AbsExtAPI.h.

◆ svfir

SVFIR* SVF::AbsExtAPI::svfir
protected

Pointer to the SVF intermediate representation.

Definition at line 132 of file AbsExtAPI.h.


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