Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | 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 (AbstractStateManager *mgr)
 Constructor for AbsExtAPI.
 
void initExtFunMap ()
 Initializes the external function map.
 
std::string strRead (const ValVar *rhs, const ICFGNode *node)
 Reads a string from the abstract state.
 
void handleExtAPI (const CallICFGNode *call)
 Handles an external API call.
 
u32_t getElementSize (const ValVar *var)
 Get the byte size of each element for a pointer/array variable.
 
IntervalValue getStrlen (const ValVar *strValue, const ICFGNode *node)
 Calculate the length of a null-terminated string in abstract state.
 
void handleStrcpy (const CallICFGNode *call)
 
void handleStrcat (const CallICFGNode *call)
 
void handleStrncat (const CallICFGNode *call)
 
void handleMemcpy (const ValVar *dst, const ValVar *src, const IntervalValue &len, u32_t start_idx, const ICFGNode *node)
 Core memcpy: copy len bytes from src to dst starting at dst[start_idx].
 
void handleMemset (const ValVar *dst, const IntervalValue &elem, const IntervalValue &len, const ICFGNode *node)
 
IntervalValue getRangeLimitFromType (const SVFType *type)
 Gets the range limit from a type.
 
AbstractStategetAbstractState (const ICFGNode *node)
 Retrieves the abstract state from the trace for a given ICFG node.
 
void collectCheckPoint ()
 
void checkPointAllSet ()
 

Static Public Member Functions

static bool isValidLength (const IntervalValue &len)
 Check if an interval length is usable (not bottom, not unbounded).
 

Public Attributes

Set< const CallICFGNode * > checkpoints
 

Protected Attributes

AbstractStateManagermgr
 Pointer to the state manager.
 
SVFIRsvfir
 Pointer to the SVF intermediate representation.
 
ICFGicfg
 Pointer to the interprocedural control flow graph.
 
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 ( AbstractStateManager mgr)

Constructor for AbsExtAPI.

Parameters
aeReference to the AbstractInterpretation instance.

Definition at line 35 of file AbsExtAPI.cpp.

35 : mgr(mgr)
36{
38 icfg = svfir->getICFG();
40}
AbstractStateManager * mgr
Pointer to the state manager.
Definition AbsExtAPI.h:117
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:42
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition AbsExtAPI.h:118
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:119
ICFG * getICFG() const
Definition SVFIR.h:229
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:118

Member Function Documentation

◆ checkPointAllSet()

void AbsExtAPI::checkPointAllSet ( )

Definition at line 345 of file AbsExtAPI.cpp.

346{
347 if (checkpoints.size() == 0)
348 {
349 return;
350 }
351 else
352 {
353 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
354 for (const CallICFGNode* call: checkpoints)
355 SVFUtil::errs() << call->toString() + "\n";
356 assert(false);
357 }
358}
Set< const CallICFGNode * > checkpoints
Definition AbsExtAPI.h:114
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
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ collectCheckPoint()

void AbsExtAPI::collectCheckPoint ( )

Definition at line 305 of file AbsExtAPI.cpp.

306{
307 // traverse every ICFGNode
308 Set<std::string> ae_checkpoint_names = {"svf_assert"};
309 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
310 Set<std::string> nullptr_checkpoint_names = {"UNSAFE_LOAD", "SAFE_LOAD"};
311
312 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
313 {
314 const ICFGNode* node = it->second;
315 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
316 {
317 if (const FunObjVar *fun = call->getCalledFunction())
318 {
319 if (ae_checkpoint_names.find(fun->getName()) !=
321 {
322 checkpoints.insert(call);
323 }
325 {
326 if (buf_checkpoint_names.find(fun->getName()) !=
328 {
329 checkpoints.insert(call);
330 }
331 }
333 {
334 if (nullptr_checkpoint_names.find(fun->getName()) !=
336 {
337 checkpoints.insert(call);
338 }
339 }
340 }
341 }
342 }
343}
iterator begin()
Iterators.
static const Option< bool > NullDerefCheck
nullptr dereference checker, Default: false
Definition Options.h:254
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:252

◆ getAbstractState()

AbstractState & AbsExtAPI::getAbstractState ( 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 300 of file AbsExtAPI.cpp.

301{
302 return mgr->getAbstractState(node);
303}
AbstractState & getAbstractState(const ICFGNode *node)
Retrieve the abstract state for a given ICFG node. Asserts if absent.

◆ getElementSize()

u32_t AbsExtAPI::getElementSize ( const ValVar var)

Get the byte size of each element for a pointer/array variable.

Get the byte size of each element for a pointer/array variable. Shared by handleMemcpy, handleMemset, and getStrlen to avoid duplication.

Definition at line 464 of file AbsExtAPI.cpp.

465{
466 if (var->getType()->isArrayTy())
467 {
468 return SVFUtil::dyn_cast<SVFArrayType>(var->getType())
469 ->getTypeOfElement()->getByteSize();
470 }
471 if (var->getType()->isPointerTy())
472 return 1;
473 assert(false && "unsupported type for element size");
474 return 1;
475}

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

681{
682 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
683 {
684 u32_t bits = type->getByteSize() * 8;
685 s64_t ub = 0;
686 s64_t lb = 0;
687 if (bits >= 32)
688 {
689 if (intType->isSigned())
690 {
691 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
692 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
693 }
694 else
695 {
696 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
697 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
698 }
699 }
700 else if (bits == 16)
701 {
702 if (intType->isSigned())
703 {
704 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
705 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
706 }
707 else
708 {
709 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
710 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
711 }
712 }
713 else if (bits == 8)
714 {
715 if (intType->isSigned())
716 {
717 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
718 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
719 }
720 else
721 {
722 ub = static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
723 lb = static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
724 }
725 }
726 return IntervalValue(lb, ub);
727 }
728 else if (SVFUtil::isa<SVFOtherType>(type))
729 {
730 // handle other type like float double, set s32_t as the range
731 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
732 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
733 return IntervalValue(lb, ub);
734 }
735 else
736 {
737 return IntervalValue::top();
738 // other types, return top interval
739 }
740}
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 ( const ValVar strValue,
const ICFGNode node 
)

Calculate the length of a null-terminated string in abstract state.

Calculate the length of a null-terminated string in abstract state. Scans memory from the base of strValue looking for a '\0' byte. Returns an IntervalValue: exact length if '\0' found, otherwise [0, MaxFieldLimit].

Definition at line 488 of file AbsExtAPI.cpp.

489{
491 // Step 1: determine the buffer size (in bytes) backing this pointer
492 u32_t dst_size = 0;
494 for (const auto& addr : ptrVal.getAddrs())
495 {
496 NodeID objId = as.getIDFromAddr(addr);
498 {
500 }
501 else
502 {
503 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
504 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
505 {
506 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
507 {
509 }
510 }
511 }
512 }
513
514 // Step 2: scan for '\0' terminator
515 u32_t len = 0;
516 if (mgr->getAbstractValue(strValue, node).isAddr())
517 {
518 for (u32_t index = 0; index < dst_size; index++)
519 {
523 for (const auto &addr: expr0.getAddrs())
524 {
525 val.join_with(as.load(addr));
526 }
527 if (val.getInterval().is_numeral() &&
528 (char) val.getInterval().getIntNumeral() == '\0')
529 {
530 break;
531 }
532 ++len;
533 }
534 }
535
536 // Step 3: scale by element size and return
538 if (len == 0)
540 return IntervalValue(len * elemSize);
541}
int index
Definition cJSON.h:170
u32_t getElementSize(const ValVar *var)
Get the byte size of each element for a pointer/array variable.
AbstractState & getAbstractState(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
u32_t getAllocaInstByteSize(const AddrStmt *addr)
Get the byte size of a stack allocation.
const AbstractValue & getAbstractValue(const ValVar *var, const ICFGNode *node)
AddressValue getGepObjAddrs(const ValVar *pointer, IntervalValue offset)
Compute GEP object addresses for a pointer at a given element offset.
void join_with(const AbstractValue &other)
bool isAddr() const
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:496
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 389 of file AbsExtAPI.cpp.

390{
391 const FunObjVar *fun = call->getCalledFunction();
392 assert(fun && "FunObjVar* is nullptr");
394 // get type of mem api
395 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
396 {
397 if (annotation.find("MEMCPY") != std::string::npos)
398 extType = MEMCPY;
399 if (annotation.find("MEMSET") != std::string::npos)
400 extType = MEMSET;
401 if (annotation.find("STRCPY") != std::string::npos)
402 extType = STRCPY;
403 if (annotation.find("STRCAT") != std::string::npos)
404 extType = STRCAT;
405 }
406 if (extType == UNCLASSIFIED)
407 {
408 if (func_map.find(fun->getName()) != func_map.end())
409 {
410 func_map[fun->getName()](call);
411 }
412 else
413 {
414 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
415 {
416 const AbstractValue& retVal = mgr->getAbstractValue(ret, call);
417 if (!retVal.isAddr())
418 {
420 }
421 }
422 return;
423 }
424 }
425 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
426 else if (extType == MEMCPY)
427 {
428 IntervalValue len = mgr->getAbstractValue(call->getArgument(2), call).getInterval();
429 handleMemcpy(call->getArgument(0), call->getArgument(1), len, 0, call);
430 }
431 else if (extType == MEMSET)
432 {
435 handleMemset(call->getArgument(0), elem, len, call);
436 }
437 else if (extType == STRCPY)
438 {
439 handleStrcpy(call);
440 }
441 else if (extType == STRCAT)
442 {
443 // Both strcat and strncat are annotated as STRCAT.
444 // Distinguish by name: strncat/wcsncat contain "ncat".
445 const std::string& name = fun->getName();
446 if (name.find("ncat") != std::string::npos)
447 handleStrncat(call);
448 else
449 handleStrcat(call);
450 }
451 else
452 {
453
454 }
455 return;
456}
const char *const name
Definition cJSON.h:264
void handleMemcpy(const ValVar *dst, const ValVar *src, const IntervalValue &len, u32_t start_idx, const ICFGNode *node)
Core memcpy: copy len bytes from src to dst starting at dst[start_idx].
void handleStrncat(const CallICFGNode *call)
void handleMemset(const ValVar *dst, const IntervalValue &elem, const IntervalValue &len, const ICFGNode *node)
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
void handleStrcat(const CallICFGNode *call)
void handleStrcpy(const CallICFGNode *call)
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
Definition AbsExtAPI.h:120
void updateAbstractValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node)
Write a top-level variable's abstract value into abstractTrace[node].
IntervalValue & getInterval()
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:482
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:500
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:439
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:624
virtual const std::string & getName() const
Definition SVFValue.h:189

◆ handleMemcpy()

void AbsExtAPI::handleMemcpy ( const ValVar dst,
const ValVar src,
const IntervalValue len,
u32_t  start_idx,
const ICFGNode node 
)

Core memcpy: copy len bytes from src to dst starting at dst[start_idx].

Definition at line 583 of file AbsExtAPI.cpp.

586{
587 if (!isValidLength(len)) return;
589
591 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
592 (u32_t)len.lb().getIntNumeral());
593 u32_t range_val = size / elemSize;
594
595 if (!mgr->getAbstractValue(src, node).isAddr() || !mgr->getAbstractValue(dst, node).isAddr())
596 return;
597
598 for (u32_t index = 0; index < range_val; index++)
599 {
604 for (const auto &dstAddr: expr_dst.getAddrs())
605 {
606 for (const auto &srcAddr: expr_src.getAddrs())
607 {
608 u32_t objId = as.getIDFromAddr(srcAddr);
609 if (as.inAddrToValTable(objId) || as.inAddrToAddrsTable(objId))
610 {
611 as.store(dstAddr, as.load(srcAddr));
612 }
613 }
614 }
615 }
616}
static bool isValidLength(const IntervalValue &len)
Check if an interval length is usable (not bottom, not unbounded).

◆ handleMemset()

void AbsExtAPI::handleMemset ( const ValVar dst,
const IntervalValue elem,
const IntervalValue len,
const ICFGNode node 
)

Core memset: fill dst with elem for len bytes. Note: elemSize here uses the pointee type's full size (not array element size) to match how LLVM memset/wmemset intrinsics measure len. For a pointer to wchar_t[100], elemSize = sizeof(wchar_t[100]), so range_val reflects the number of top-level GEP fields, not individual array elements.

Definition at line 623 of file AbsExtAPI.cpp.

625{
626 if (!isValidLength(len)) return;
628
629 u32_t elemSize = 1;
630 if (dst->getType()->isArrayTy())
631 {
632 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())
633 ->getTypeOfElement()->getByteSize();
634 }
635 else if (dst->getType()->isPointerTy())
636 {
637 elemSize = 1;
638 }
639 else
640 {
641 assert(false && "unsupported type for element size");
642 }
643 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
644 (u32_t)len.lb().getIntNumeral());
645 u32_t range_val = size / elemSize;
646
647 for (u32_t index = 0; index < range_val; index++)
648 {
649 if (!mgr->getAbstractValue(dst, node).isAddr())
650 break;
652 for (const auto &addr: lhs_gep.getAddrs())
653 {
654 u32_t objId = as.getIDFromAddr(addr);
655 if (as.inAddrToValTable(objId))
656 {
657 AbstractValue tmp = as.load(addr);
659 as.store(addr, tmp);
660 }
661 else
662 {
663 as.store(addr, elem);
664 }
665 }
666 }
667}
bool isArrayTy() const
Definition SVFType.h:299
bool isPointerTy() const
Definition SVFType.h:294
virtual const SVFType * getType() const
Definition SVFValue.h:174

◆ handleStrcat()

void AbsExtAPI::handleStrcat ( const CallICFGNode call)

strcat(dst, src): append all of src after the end of dst. Covers: strcat, __strcat_chk, wcscat, __wcscat_chk

Definition at line 560 of file AbsExtAPI.cpp.

561{
562 const ValVar* dst = call->getArgument(0);
563 const ValVar* src = call->getArgument(1);
564 IntervalValue dstLen = getStrlen(dst, call);
565 IntervalValue srcLen = getStrlen(src, call);
566 if (!isValidLength(dstLen)) return;
567 handleMemcpy(dst, src, srcLen, dstLen.lb().getIntNumeral(), call);
568}
IntervalValue getStrlen(const ValVar *strValue, const ICFGNode *node)
Calculate the length of a null-terminated string in abstract state.

◆ handleStrcpy()

void AbsExtAPI::handleStrcpy ( const CallICFGNode call)

strcpy(dst, src): copy all of src (including '\0') into dst. Covers: strcpy, __strcpy_chk, stpcpy, wcscpy, __wcscpy_chk

Definition at line 549 of file AbsExtAPI.cpp.

550{
551 const ValVar* dst = call->getArgument(0);
552 const ValVar* src = call->getArgument(1);
553 IntervalValue srcLen = getStrlen(src, call);
554 if (!isValidLength(srcLen)) return;
555 handleMemcpy(dst, src, srcLen, 0, call);
556}

◆ handleStrncat()

void AbsExtAPI::handleStrncat ( const CallICFGNode call)

strncat(dst, src, n): append at most n bytes of src after the end of dst. Covers: strncat, __strncat_chk, wcsncat, __wcsncat_chk

Definition at line 572 of file AbsExtAPI.cpp.

573{
574 const ValVar* dst = call->getArgument(0);
575 const ValVar* src = call->getArgument(1);
577 IntervalValue dstLen = getStrlen(dst, call);
578 if (!isValidLength(dstLen)) return;
579 handleMemcpy(dst, src, n, dstLen.lb().getIntNumeral(), call);
580}
cJSON * n
Definition cJSON.cpp:2558

◆ 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 const SVFVar* argVar = callNode->getArgument(0); \
48 const AbstractValue& argVal = mgr->getAbstractValue(argVar, callNode); \
49 if (!argVal.isInterval() && !argVal.isAddr()) return; \
50 u32_t rhs = argVal.getInterval().lb().getIntNumeral(); \
51 s32_t res = FUNC_NAME(rhs); \
52 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet(); \
53 mgr->updateAbstractValue(retVar, IntervalValue(res), callNode); \
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 {
79 checkpoints.erase(callNode);
80 const AbstractValue& arg0Val = mgr->getAbstractValue(callNode->getArgument(0), callNode);
81 if (arg0Val.getInterval().equals(IntervalValue(1, 1)))
82 {
83 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
84 }
85 else
86 {
87 SVFUtil::errs() << SVFUtil::errMsg("Assertion failure, this svf_assert cannot be verified!!\n") << callNode->toString() << "\n";
88 assert(false);
89 }
90 return;
91 };
92 func_map["svf_assert"] = sse_svf_assert;
93
94 auto svf_assert_eq = [this](const CallICFGNode* callNode)
95 {
96 const AbstractValue& arg0Val = mgr->getAbstractValue(callNode->getArgument(0), callNode);
97 const AbstractValue& arg1Val = mgr->getAbstractValue(callNode->getArgument(1), callNode);
98 if (arg0Val.getInterval().equals(arg1Val.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;
114 std::string text = strRead(callNode->getArgument(1), callNode);
116 std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
117 << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
118 return;
119 };
120 func_map["svf_print"] = svf_print;
121
122 auto svf_set_value = [&](const CallICFGNode* callNode)
123 {
124 if (callNode->arg_size() < 2) return;
126 const AbstractValue& lbVal = mgr->getAbstractValue(callNode->getArgument(1), callNode);
127 const AbstractValue& ubVal = mgr->getAbstractValue(callNode->getArgument(2), callNode);
128 assert(lbVal.getInterval().is_numeral() && ubVal.getInterval().is_numeral());
131 num.getInterval().meet_with(IntervalValue(lbVal.getInterval().lb(), ubVal.getInterval().ub()));
132 mgr->updateAbstractValue(callNode->getArgument(0), num, callNode);
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);
140 for (auto addr : ptrVal.getAddrs())
141 as.store(addr, num);
142 }
143 }
144 return;
145 };
146 func_map["set_value"] = svf_set_value;
147
148 auto sse_scanf = [&](const CallICFGNode* callNode)
149 {
150 //scanf("%d", &data);
151 if (callNode->arg_size() < 2) return;
153 const AbstractValue& dstVal = mgr->getAbstractValue(callNode->getArgument(1), callNode);
154 if (!dstVal.isAddr()) return;
155 for (auto vaddr: dstVal.getAddrs())
156 {
157 u32_t objId = as.getIDFromAddr(vaddr);
159 as.store(vaddr, range);
160 }
161 };
162 auto sse_fscanf = [&](const CallICFGNode* callNode)
163 {
164 //fscanf(stdin, "%d", &data);
165 if (callNode->arg_size() < 3) return;
167 const AbstractValue& dstVal = mgr->getAbstractValue(callNode->getArgument(2), callNode);
168 if (!dstVal.isAddr()) return;
169 for (auto vaddr: dstVal.getAddrs())
170 {
171 u32_t objId = as.getIDFromAddr(vaddr);
173 as.store(vaddr, range);
174 }
175 };
176
177 func_map["__isoc99_fscanf"] = sse_fscanf;
178 func_map["__isoc99_scanf"] = sse_scanf;
179 func_map["__isoc99_vscanf"] = sse_scanf;
180 func_map["fscanf"] = sse_fscanf;
181 func_map["scanf"] = sse_scanf;
182 func_map["sscanf"] = sse_scanf;
183 func_map["__isoc99_sscanf"] = sse_scanf;
184 func_map["vscanf"] = sse_scanf;
185
186 auto sse_fread = [&](const CallICFGNode *callNode)
187 {
188 if (callNode->arg_size() < 3) return;
189 IntervalValue block_count = mgr->getAbstractValue(callNode->getArgument(2), callNode).getInterval();
190 IntervalValue block_size = mgr->getAbstractValue(callNode->getArgument(1), callNode).getInterval();
192 (void)block_byte;
193 };
194 func_map["fread"] = sse_fread;
195
196 auto sse_sprintf = [&](const CallICFGNode *callNode)
197 {
198 // printf is difficult to predict since it has no byte size arguments
199 };
200
201 auto sse_snprintf = [&](const CallICFGNode *callNode)
202 {
203 if (callNode->arg_size() < 2) return;
204 // get elem size of arg2
205 u32_t elemSize = 1;
206 if (callNode->getArgument(2)->getType()->isArrayTy())
207 {
208 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
209 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
210 }
211 else if (callNode->getArgument(2)->getType()->isPointerTy())
212 {
213 elemSize = 1;
214 }
215 else
216 {
217 return;
218 }
221 (void)size;
222 };
223 func_map["__snprintf_chk"] = sse_snprintf;
224 func_map["__vsprintf_chk"] = sse_sprintf;
225 func_map["__sprintf_chk"] = sse_sprintf;
226 func_map["snprintf"] = sse_snprintf;
227 func_map["sprintf"] = sse_sprintf;
228 func_map["vsprintf"] = sse_sprintf;
229 func_map["vsnprintf"] = sse_snprintf;
230 func_map["__vsnprintf_chk"] = sse_snprintf;
231 func_map["swprintf"] = sse_snprintf;
232 func_map["_snwprintf"] = sse_snprintf;
233
234
235 auto sse_itoa = [&](const CallICFGNode* callNode)
236 {
237 if (callNode->arg_size() < 3) return;
238 u32_t num = (u32_t) mgr->getAbstractValue(callNode->getArgument(0), callNode).getInterval().getNumeral();
239 std::string snum = std::to_string(num);
240 (void)snum;
241 };
242 func_map["itoa"] = sse_itoa;
243
244
245 auto sse_strlen = [&](const CallICFGNode *callNode)
246 {
247 if (callNode->arg_size() < 1) return;
248 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
249 IntervalValue byteLen = getStrlen(callNode->getArgument(0), callNode);
250 u32_t elemSize = getElementSize(callNode->getArgument(0));
251 if (byteLen.is_numeral() && elemSize > 1)
253 else
255 };
256 func_map["strlen"] = sse_strlen;
257 func_map["wcslen"] = sse_strlen;
258
259 auto sse_recv = [&](const CallICFGNode *callNode)
260 {
261 if (callNode->arg_size() < 4) return;
262 IntervalValue len = mgr->getAbstractValue(callNode->getArgument(2), callNode).getInterval() - IntervalValue(1);
263 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
265 };
266 func_map["recv"] = sse_recv;
267 func_map["__recv"] = sse_recv;
268
269 auto sse_free = [&](const CallICFGNode *callNode)
270 {
271 if (callNode->arg_size() < 1) return;
273 const AbstractValue& ptrVal = mgr->getAbstractValue(callNode->getArgument(0), callNode);
274 for (auto addr: ptrVal.getAddrs())
275 {
277 {
278 }
279 else
280 {
281 as.addToFreedAddrs(addr);
282 }
283 }
284 };
285 // Add all free-related functions to func_map
286 std::vector<std::string> freeFunctions =
287 {
288 "VOS_MemFree", "cfree", "free", "free_all_mem", "freeaddrinfo",
289 "gcry_mpi_release", "gcry_sexp_release", "globfree", "nhfree",
290 "obstack_free", "safe_cfree", "safe_free", "safefree", "safexfree",
291 "sm_free", "vim_free", "xfree", "SSL_CTX_free", "SSL_free", "XFree"
292 };
293
294 for (const auto& name : freeFunctions)
295 {
297 }
298};
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(const ValVar *rhs, const ICFGNode *node)
Reads a string from the abstract state.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
static bool isBlackHoleObjAddr(u32_t addr)
const std::string toString() const
void set_to_top()
Set current IntervalValue as top.
const ValVar * getRHSVar() const
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:133
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
unsigned u32_t
Definition GeneralType.h:47

◆ isValidLength()

bool AbsExtAPI::isValidLength ( const IntervalValue len)
static

Check if an interval length is usable (not bottom, not unbounded).

Check if an interval length is usable for memory operations. Returns false for bottom (no information) or unbounded lower bound (cannot determine a concrete start for iteration).

Definition at line 480 of file AbsExtAPI.cpp.

481{
482 return !len.isBottom() && !len.lb().is_minus_infinity();
483}

◆ strRead()

std::string AbsExtAPI::strRead ( const ValVar rhs,
const ICFGNode node 
)

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

361{
363 std::string str0;
364
366 {
367 if (!mgr->getAbstractValue(rhs, node).isAddr()) continue;
370
372 for (const auto &addr: expr0.getAddrs())
373 {
374 val.join_with(as.load(addr));
375 }
376 if (!val.getInterval().is_numeral())
377 {
378 break;
379 }
380 if ((char) val.getInterval().getIntNumeral() == '\0')
381 {
382 break;
383 }
384 str0.push_back((char) val.getInterval().getIntNumeral());
385 }
386 return str0;
387}

Member Data Documentation

◆ checkpoints

Set<const CallICFGNode*> SVF::AbsExtAPI::checkpoints

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

◆ icfg

ICFG* SVF::AbsExtAPI::icfg
protected

Pointer to the interprocedural control flow graph.

Definition at line 119 of file AbsExtAPI.h.

◆ mgr

AbstractStateManager* SVF::AbsExtAPI::mgr
protected

Pointer to the state manager.

Definition at line 117 of file AbsExtAPI.h.

◆ svfir

SVFIR* SVF::AbsExtAPI::svfir
protected

Pointer to the SVF intermediate representation.

Definition at line 118 of file AbsExtAPI.h.


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