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

36{
38 icfg = svfir->getICFG();
40}
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:42
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 379 of file AbsExtAPI.cpp.

380{
381 if (abstractTrace.count(node) == 0)
382 {
383 assert(0 && "No preAbsTrace for this node");
384 abort();
385 }
386 else
387 {
388 return abstractTrace[node];
389 }
390}

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

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

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

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

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

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

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

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

◆ handleStrcat()

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

Handles the strcat API call.

Parameters
callPointer to the call ICFG node.

Definition at line 580 of file AbsExtAPI.cpp.

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

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

◆ initExtFunMap()

void AbsExtAPI::initExtFunMap ( )

Initializes the external function map.

Definition at line 42 of file AbsExtAPI.cpp.

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

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

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: