Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Protected Attributes | Private Member Functions | Friends | 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

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.
 
AbstractState & getAbsState (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).
 
static u32_t getBoundedMinimumByteCount (const IntervalValue &len)
 Return the lower bound of len, capped by the field limit.
 

Public Attributes

Set< const CallICFGNode * > checkpoints
 

Protected Attributes

AbstractInterpretation * ae
 Owning AbstractInterpretation; provides state access.
 
SVFIR * svfir
 Pointer to the SVF intermediate representation.
 
ICFG * icfg
 Pointer to the interprocedural control flow graph.
 
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
 Map of function names to handlers.
 

Private Member Functions

 AbsExtAPI (AbstractInterpretation *ae)
 Constructor for AbsExtAPI.
 

Friends

class AbstractInterpretation
 

Detailed Description

Handles external API calls and manages abstract states.

Definition at line 48 of file AbsExtAPI.h.

Member Enumeration Documentation

◆ ExtAPIType

Enumeration of external API types.

Enumerator
UNCLASSIFIED 
MEMCPY 
MEMSET 
STRCPY 
STRCAT 

Definition at line 55 of file AbsExtAPI.h.

Constructor & Destructor Documentation

◆ AbsExtAPI()

AbsExtAPI::AbsExtAPI ( AbstractInterpretation *  ae)
private

Constructor for AbsExtAPI.

Parameters
aeReference to the AbstractInterpretation instance.

Definition at line 35 of file AbsExtAPI.cpp.

35 : ae(ae)
36{
38 icfg = svfir->getICFG();
40}
AbstractInterpretation * ae
Owning AbstractInterpretation; provides state access.
Definition AbsExtAPI.h:132
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:42
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition AbsExtAPI.h:133
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:134
ICFG * getICFG() const
Definition SVFIR.h:232
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:121

Member Function Documentation

◆ checkPointAllSet()

void AbsExtAPI::checkPointAllSet ( )

Definition at line 298 of file AbsExtAPI.cpp.

299{
300 if (!checkpoints.empty())
301 {
302 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
303 for (const CallICFGNode* call: checkpoints)
304 SVFUtil::errs() << call->toString() + "\n";
305 assert(false);
306 }
307}
Set< const CallICFGNode * > checkpoints
Definition AbsExtAPI.h:129
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:98
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ collectCheckPoint()

void AbsExtAPI::collectCheckPoint ( )

Definition at line 258 of file AbsExtAPI.cpp.

259{
260 // traverse every ICFGNode
261 Set<std::string> ae_checkpoint_names = {"svf_assert"};
262 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
263 Set<std::string> nullptr_checkpoint_names = {"UNSAFE_LOAD", "SAFE_LOAD"};
264
265 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
266 {
267 const ICFGNode* node = it->second;
268 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
269 {
270 if (const FunObjVar *fun = call->getCalledFunction())
271 {
272 if (ae_checkpoint_names.find(fun->getName()) !=
274 {
275 checkpoints.insert(call);
276 }
278 {
279 if (buf_checkpoint_names.find(fun->getName()) !=
281 {
282 checkpoints.insert(call);
283 }
284 }
286 {
287 if (nullptr_checkpoint_names.find(fun->getName()) !=
289 {
290 checkpoints.insert(call);
291 }
292 }
293 }
294 }
295 }
296}
iterator begin()
Iterators.
static const Option< bool > NullDerefCheck
nullptr dereference checker, Default: false
Definition Options.h:249
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:247

◆ getAbsState()

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

254{
255 return ae->getAbsState(node);
256}
AbstractState & getAbsState(const ICFGNode *node)

◆ getBoundedMinimumByteCount()

u32_t AbsExtAPI::getBoundedMinimumByteCount ( const IntervalValue &  len)
static

Return the lower bound of len, capped by the field limit.

Definition at line 429 of file AbsExtAPI.cpp.

430{
431 u32_t byteCount = 0;
432 if (isValidLength(len) && len.lb().getIntNumeral() > 0)
433 {
435 (u32_t)len.lb().getIntNumeral());
436 }
437 return byteCount;
438}
unsigned u32_t
Definition CommandLine.h:18
static bool isValidLength(const IntervalValue &len)
Check if an interval length is usable (not bottom, not unbounded).
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34

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

409{
410 if (var->getType()->isArrayTy())
411 {
412 return SVFUtil::dyn_cast<SVFArrayType>(var->getType())
413 ->getTypeOfElement()->getByteSize();
414 }
415 if (var->getType()->isPointerTy())
416 return 1;
417 assert(false && "unsupported type for element size");
418 return 1;
419}

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

627{
628 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
629 {
630 u32_t bits = type->getByteSize() * 8;
631 s64_t ub = 0;
632 s64_t lb = 0;
633 if (bits >= 32)
634 {
635 if (intType->isSigned())
636 {
637 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
638 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
639 }
640 else
641 {
642 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
643 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
644 }
645 }
646 else if (bits == 16)
647 {
648 if (intType->isSigned())
649 {
650 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
651 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
652 }
653 else
654 {
655 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
656 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
657 }
658 }
659 else if (bits == 8)
660 {
661 if (intType->isSigned())
662 {
663 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
664 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
665 }
666 else
667 {
668 ub = static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
669 lb = static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
670 }
671 }
672 return IntervalValue(lb, ub);
673 }
674 else if (SVFUtil::isa<SVFOtherType>(type))
675 {
676 // handle other type like float double, set s32_t as the range
677 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
678 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
679 return IntervalValue(lb, ub);
680 }
681 else
682 {
683 return IntervalValue::top();
684 // other types, return top interval
685 }
686}
newitem type
Definition cJSON.cpp:2739
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
signed long long s64_t
Definition GeneralType.h:70

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

444{
446 // Step 1: determine the buffer size (in bytes) backing this pointer
447 u32_t dst_size = 0;
448 const AbstractValue& ptrVal = ae->getAbsValue(strValue, node);
449 for (const auto& addr : ptrVal.getAddrs())
450 {
451 // Unknown and null pointers have no concrete backing buffer to inspect.
453 continue;
454 NodeID objId = as.getIDFromAddr(addr);
456 {
458 }
459 else
460 {
461 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
462 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
463 {
464 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
465 {
467 }
468 }
469 }
470 }
471
472 // Step 2: scan for '\0' terminator
473 u32_t len = 0;
474 for (u32_t index = 0; index < dst_size; index++)
475 {
479 for (const auto &addr: expr0.getAddrs())
480 {
481 val.join_with(as.load(addr));
482 }
483 if (val.getInterval().is_numeral() &&
484 (char) val.getInterval().getIntNumeral() == '\0')
485 {
486 break;
487 }
488 ++len;
489 }
490
491 // Step 3: scale by element size and return
493 if (len == 0)
495 return IntervalValue(len * elemSize);
496}
int index
Definition cJSON.h:170
AbstractState & getAbsState(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
u32_t getElementSize(const ValVar *var)
Get the byte size of each element for a pointer/array variable.
AddressValue getGepObjAddrs(const ValVar *pointer, IntervalValue offset)
virtual const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node)
AllocationSizeBounds getAllocaInstByteSize(const AddrStmt *addr)
static bool isNullOrBlackHoleAddr(u32_t addr)
Whether addr has no concrete backing memory object.
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.
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:499
u32_t NodeID
Definition GeneralType.h:76

◆ handleExtAPI()

void AbsExtAPI::handleExtAPI ( const CallICFGNode *  call)

Handles an external API call.

Parameters
callPointer to the call ICFG node.

Definition at line 337 of file AbsExtAPI.cpp.

338{
339 const FunObjVar *fun = call->getCalledFunction();
340 assert(fun && "FunObjVar* is nullptr");
342 // get type of mem api
343 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
344 {
345 if (annotation.find("MEMCPY") != std::string::npos)
346 extType = MEMCPY;
347 if (annotation.find("MEMSET") != std::string::npos)
348 extType = MEMSET;
349 if (annotation.find("STRCPY") != std::string::npos)
350 extType = STRCPY;
351 if (annotation.find("STRCAT") != std::string::npos)
352 extType = STRCAT;
353 }
354 if (extType == UNCLASSIFIED)
355 {
356 if (func_map.find(fun->getName()) != func_map.end())
357 {
358 func_map[fun->getName()](call);
359 }
360 else
361 {
362 const SVFVar* ret = call->getRetICFGNode()->getActualRet();
363 if (ret && !ret->getType()->isPointerTy())
364 {
365 ae->updateAbsValue(ret, IntervalValue(), call);
366 }
367 }
368 }
369 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
370 else if (extType == MEMCPY)
371 {
372 IntervalValue len = ae->getAbsValue(call->getArgument(2), call).getInterval();
373 handleMemcpy(call->getArgument(0), call->getArgument(1), len, 0, call);
374 }
375 else if (extType == MEMSET)
376 {
379 handleMemset(call->getArgument(0), elem, len, call);
380 }
381 else if (extType == STRCPY)
382 {
383 handleStrcpy(call);
384 }
385 else if (extType == STRCAT)
386 {
387 // Both strcat and strncat are annotated as STRCAT.
388 // Distinguish by name: strncat/wcsncat contain "ncat".
389 const std::string& name = fun->getName();
390 if (name.find("ncat") != std::string::npos)
391 handleStrncat(call);
392 else
393 handleStrcat(call);
394 }
395 else
396 {
397
398 }
399 return;
400}
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:55
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:135
virtual void updateAbsValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node)
IntervalValue & getInterval()
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:483
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:501
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:440
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:625
bool isPointerTy() const
Definition SVFType.h:292
virtual const SVFType * getType() const
Definition SVFValue.h:169
virtual const std::string & getName() const
Definition SVFValue.h:184

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

541{
543
546 u32_t range_val = size / elemSize;
547
548 for (u32_t index = 0; index < range_val; index++)
549 {
554 for (const auto &dstAddr: expr_dst.getAddrs())
555 {
556 for (const auto &srcAddr: expr_src.getAddrs())
557 {
558 u32_t objId = as.getIDFromAddr(srcAddr);
559 if (as.inAddrToValTable(objId) || as.inAddrToAddrsTable(objId))
560 {
561 as.store(dstAddr, as.load(srcAddr));
562 }
563 }
564 }
565 }
566}
static u32_t getBoundedMinimumByteCount(const IntervalValue &len)
Return the lower bound of len, capped by the field limit.

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

575{
577
578 u32_t elemSize = 1;
579 if (dst->getType()->isArrayTy())
580 {
581 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())
582 ->getTypeOfElement()->getByteSize();
583 }
584 else if (dst->getType()->isPointerTy())
585 {
586 elemSize = 1;
587 }
588 else
589 {
590 assert(false && "unsupported type for element size");
591 }
593 u32_t range_val = size / elemSize;
594
595 for (u32_t index = 0; index < range_val; index++)
596 {
598 for (const auto &addr: lhs_gep.getAddrs())
599 {
600 u32_t objId = as.getIDFromAddr(addr);
601 if (as.inAddrToValTable(objId))
602 {
603 AbstractValue tmp = as.load(addr);
605 as.store(addr, tmp);
606 }
607 else
608 {
609 as.store(addr, elem);
610 }
611 }
612 }
613}
bool isArrayTy() const
Definition SVFType.h:297

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

516{
517 const ValVar* dst = call->getArgument(0);
518 const ValVar* src = call->getArgument(1);
519 IntervalValue dstLen = getStrlen(dst, call);
520 IntervalValue srcLen = getStrlen(src, call);
521 assert(isValidLength(dstLen) && "getStrlen must return a bounded length");
522 handleMemcpy(dst, src, srcLen, dstLen.lb().getIntNumeral(), call);
523}
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 504 of file AbsExtAPI.cpp.

505{
506 const ValVar* dst = call->getArgument(0);
507 const ValVar* src = call->getArgument(1);
508 IntervalValue srcLen = getStrlen(src, call);
509 assert(isValidLength(srcLen) && "getStrlen must return a bounded length");
510 handleMemcpy(dst, src, srcLen, 0, call);
511}

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

528{
529 const ValVar* dst = call->getArgument(0);
530 const ValVar* src = call->getArgument(1);
532 IntervalValue dstLen = getStrlen(dst, call);
533 assert(isValidLength(dstLen) && "getStrlen must return a bounded length");
534 handleMemcpy(dst, src, n, dstLen.lb().getIntNumeral(), call);
535}
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 assert(callNode->arg_size() >= 1 && "external function expects one argument"); \
48 const SVFVar* argVar = callNode->getArgument(0); \
49 const AbstractValue& argVal = ae->getAbsValue(argVar, callNode); \
50 IntervalValue result = IntervalValue::top(); \
51 if (argVal.isInterval() && argVal.getInterval().is_numeral()) { \
52 u32_t rhs = argVal.getInterval().lb().getIntNumeral(); \
53 result = IntervalValue(FUNC_NAME(rhs)); \
54 } \
55 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet(); \
56 ae->updateAbsValue(retVar, result, callNode); \
57 }; \
58 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
59
71 SSE_FUNC_PROCESS(llvm.sin.f64, sin);
72 SSE_FUNC_PROCESS(llvm.cos.f64, cos);
73 SSE_FUNC_PROCESS(llvm.tan.f64, tan);
74 SSE_FUNC_PROCESS(llvm.log.f64, log);
78
79 auto sse_svf_assert = [this](const CallICFGNode* callNode)
80 {
81 checkpoints.erase(callNode);
82 const AbstractValue& arg0Val = ae->getAbsValue(callNode->getArgument(0), callNode);
83 if (arg0Val.getInterval().equals(IntervalValue(1, 1)))
84 {
85 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
86 }
87 else
88 {
89 SVFUtil::errs() << SVFUtil::errMsg("Assertion failure, this svf_assert cannot be verified!!\n") << callNode->toString() << "\n";
90 assert(false);
91 }
92 return;
93 };
94 func_map["svf_assert"] = sse_svf_assert;
95
96 auto svf_assert_eq = [this](const CallICFGNode* callNode)
97 {
98 const AbstractValue& arg0Val = ae->getAbsValue(callNode->getArgument(0), callNode);
99 const AbstractValue& arg1Val = ae->getAbsValue(callNode->getArgument(1), callNode);
100 if (arg0Val.getInterval().equals(arg1Val.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 assert(callNode->arg_size() >= 2 && "svf_print expects two arguments");
116 std::string text = strRead(callNode->getArgument(1), callNode);
118 std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
119 << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
120 return;
121 };
122 func_map["svf_print"] = svf_print;
123
124 auto svf_set_value = [&](const CallICFGNode* callNode)
125 {
126 assert(callNode->arg_size() >= 3 && "set_value expects three arguments");
128 const AbstractValue& lbVal = ae->getAbsValue(callNode->getArgument(1), callNode);
129 const AbstractValue& ubVal = ae->getAbsValue(callNode->getArgument(2), callNode);
130 assert(lbVal.getInterval().is_numeral() && ubVal.getInterval().is_numeral());
133 num.getInterval().meet_with(IntervalValue(lbVal.getInterval().lb(), ubVal.getInterval().ub()));
134 ae->updateAbsValue(callNode->getArgument(0), num, callNode);
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);
142 for (auto addr : ptrVal.getAddrs())
143 as.store(addr, num);
144 }
145 }
146 return;
147 };
148 func_map["set_value"] = svf_set_value;
149
150 auto sse_fread = [&](const CallICFGNode *callNode)
151 {
152 assert(callNode->arg_size() >= 3 && "fread expects at least three arguments");
156 (void)block_byte;
157 };
158 func_map["fread"] = sse_fread;
159
160 auto sse_sprintf = [&](const CallICFGNode *callNode)
161 {
162 // printf is difficult to predict since it has no byte size arguments
163 };
164
165 auto sse_snprintf = [&](const CallICFGNode *callNode)
166 {
167 assert(callNode->arg_size() >= 2 &&
168 "formatted-output function expects at least two arguments");
169 u32_t elemSize = 1;
170 if (callNode->arg_size() > 2 &&
171 callNode->getArgument(2)->getType()->isArrayTy())
172 {
173 elemSize = SVFUtil::cast<SVFArrayType>(
174 callNode->getArgument(2)->getType())
175 ->getTypeOfElement()->getByteSize();
176 }
177 IntervalValue size = ae->getAbsValue(callNode->getArgument(1), callNode).getInterval()
179 (void)size;
180 };
181 func_map["__snprintf_chk"] = sse_snprintf;
182 func_map["__vsprintf_chk"] = sse_sprintf;
183 func_map["__sprintf_chk"] = sse_sprintf;
184 func_map["snprintf"] = sse_snprintf;
185 func_map["sprintf"] = sse_sprintf;
186 func_map["vsprintf"] = sse_sprintf;
187 func_map["vsnprintf"] = sse_snprintf;
188 func_map["__vsnprintf_chk"] = sse_snprintf;
189 func_map["swprintf"] = sse_snprintf;
190 func_map["_snwprintf"] = sse_snprintf;
191
192
193 auto sse_itoa = [&](const CallICFGNode* callNode)
194 {
195 assert(callNode->arg_size() >= 3 && "itoa expects three arguments");
196 u32_t num = (u32_t) ae->getAbsValue(callNode->getArgument(0), callNode).getInterval().getNumeral();
197 std::string snum = std::to_string(num);
198 (void)snum;
199 };
200 func_map["itoa"] = sse_itoa;
201
202
203 auto sse_strlen = [&](const CallICFGNode *callNode)
204 {
205 assert(callNode->arg_size() >= 1 && "strlen expects one argument");
206 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
207 IntervalValue byteLen = getStrlen(callNode->getArgument(0), callNode);
208 u32_t elemSize = getElementSize(callNode->getArgument(0));
209 if (byteLen.is_numeral() && elemSize > 1)
211 else
213 };
214 func_map["strlen"] = sse_strlen;
215 func_map["wcslen"] = sse_strlen;
216
217 auto sse_recv = [&](const CallICFGNode *callNode)
218 {
219 assert(callNode->arg_size() >= 4 && "recv expects four arguments");
221 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
223 };
224 func_map["recv"] = sse_recv;
225 func_map["__recv"] = sse_recv;
226
227 auto sse_free = [&](const CallICFGNode *callNode)
228 {
229 assert(callNode->arg_size() >= 1 && "free expects one argument");
231 const AbstractValue& ptrVal = ae->getAbsValue(callNode->getArgument(0), callNode);
232 for (auto addr: ptrVal.getAddrs())
233 {
235 as.addToFreedAddrs(addr);
236 }
237 };
238 // Add all free-related functions to func_map
239 std::vector<std::string> freeFunctions =
240 {
241 "VOS_MemFree", "cfree", "free", "free_all_mem", "freeaddrinfo",
242 "gcry_mpi_release", "gcry_sexp_release", "globfree", "nhfree",
243 "obstack_free", "safe_cfree", "safe_free", "safefree", "safexfree",
244 "sm_free", "vim_free", "xfree", "SSL_CTX_free", "SSL_free", "XFree"
245 };
246
247 for (const auto& name : freeFunctions)
248 {
250 }
251};
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(const ValVar *rhs, const ICFGNode *node)
Reads a string from the abstract state.
const std::string toString() const
void set_to_top()
Set current IntervalValue as top.
const ValVar * getRHSVar() const
int iscntrl(int c)
Definition extapi.c:1013
int isdigit(int c)
Definition extapi.c:1018
int isgraph(int c)
Definition extapi.c:1023
int isspace(char c)
Definition extapi.c:1043
int isprint(int c)
Definition extapi.c:1033
int ispunct(int argument)
Definition extapi.c:1038
int isblank(int character)
Definition extapi.c:1008
int isalnum(int character)
Definition extapi.c:998
int isupper(int c)
Definition extapi.c:1048
int isxdigit(int c)
Definition extapi.c:1053
int isalpha(int character)
Definition extapi.c:1003
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:75
unsigned u32_t
Definition GeneralType.h:67

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

425{
426 return !len.isBottom() && !len.lb().is_minus_infinity();
427}

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

310{
312 std::string str0;
313
315 {
318
320 for (const auto &addr: expr0.getAddrs())
321 {
322 val.join_with(as.load(addr));
323 }
324 if (!val.getInterval().is_numeral())
325 {
326 break;
327 }
328 if ((char) val.getInterval().getIntNumeral() == '\0')
329 {
330 break;
331 }
332 str0.push_back((char) val.getInterval().getIntNumeral());
333 }
334 return str0;
335}

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 61 of file AbsExtAPI.h.

Member Data Documentation

◆ ae

AbstractInterpretation* SVF::AbsExtAPI::ae
protected

Owning AbstractInterpretation; provides state access.

Definition at line 132 of file AbsExtAPI.h.

◆ checkpoints

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

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

◆ svfir

SVFIR* SVF::AbsExtAPI::svfir
protected

Pointer to the SVF intermediate representation.

Definition at line 133 of file AbsExtAPI.h.


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