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 abort();
384 }
385 else
386 {
387 return abstractTrace[repNode];
388 }
389}
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 735 of file AbsExtAPI.cpp.

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

504{
505 NodeID value_id = strValue->getId();
506 u32_t dst_size = 0;
507 for (const auto& addr : as[value_id].getAddrs())
508 {
509 NodeID objId = as.getIDFromAddr(addr);
511 {
513 }
514 else
515 {
516 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
517 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
518 {
519 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
520 {
521 dst_size = as.getAllocaInstByteSize(addrStmt);
522 }
523 }
524 }
525 }
526 u32_t len = 0;
527 u32_t elemSize = 1;
528 if (as.inVarToAddrsTable(value_id))
529 {
530 for (u32_t index = 0; index < dst_size; index++)
531 {
533 as.getGepObjAddrs(value_id, IntervalValue(index));
535 for (const auto &addr: expr0.getAddrs())
536 {
537 val.join_with(as.load(addr));
538 }
539 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
540 {
541 break;
542 }
543 ++len;
544 }
545 if (strValue->getType()->isArrayTy())
546 {
547 elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
548 }
549 else if (strValue->getType()->isPointerTy())
550 {
551 if (const SVFType* elemType = as.getPointeeElement(value_id))
552 {
553 if (elemType->isArrayTy())
554 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
555 else
556 elemSize = elemType->getByteSize();
557 }
558 else
559 {
560 elemSize = 1;
561 }
562 }
563 else
564 {
565 assert(false && "we cannot support this type");
566 }
567 }
568 if (len == 0)
569 {
571 }
572 else
573 {
574 return IntervalValue(len * elemSize);
575 }
576}
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:35
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 421 of file AbsExtAPI.cpp.

422{
424 const FunObjVar *fun = call->getCalledFunction();
425 assert(fun && "FunObjVar* is nullptr");
427 // get type of mem api
428 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
429 {
430 if (annotation.find("MEMCPY") != std::string::npos)
431 extType = MEMCPY;
432 if (annotation.find("MEMSET") != std::string::npos)
433 extType = MEMSET;
434 if (annotation.find("STRCPY") != std::string::npos)
435 extType = STRCPY;
436 if (annotation.find("STRCAT") != std::string::npos)
437 extType = STRCAT;
438 }
439 if (extType == UNCLASSIFIED)
440 {
441 if (func_map.find(fun->getName()) != func_map.end())
442 {
443 func_map[fun->getName()](call);
444 }
445 else
446 {
447 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
448 {
449 u32_t lhsId = ret->getId();
450 if (as.inVarToAddrsTable(lhsId))
451 {
452
453 }
454 else
455 {
457 }
458 }
459 return;
460 }
461 }
462 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
463 else if (extType == MEMCPY)
464 {
465 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
466 svfir->getGNode(call->getArgument(0)->getId());
467 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
468 }
469 else if (extType == MEMSET)
470 {
471 // memset dst is arg0, elem is arg1, size is arg2
472 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
473 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
474 handleMemset(as, call->getArgument(0), elem, len);
475 }
476 else if (extType == STRCPY)
477 {
478 handleStrcpy(call);
479 }
480 else if (extType == STRCAT)
481 {
482 handleStrcat(call);
483 }
484 else
485 {
486
487 }
488 return;
489}
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 614 of file AbsExtAPI.cpp.

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

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

◆ handleStrcat()

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

Handles the strcat API call.

Parameters
callPointer to the call ICFG node.

Definition at line 579 of file AbsExtAPI.cpp.

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

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

◆ 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() << SVFUtil::errMsg("Assertion failure, this svf_assert cannot be verified!!\n") << 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::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:78
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 391 of file AbsExtAPI.cpp.

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

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: