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.
 
AbstractStategetAbsState (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

AbstractInterpretationae
 Owning AbstractInterpretation; provides state access.
 
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.
 

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

Member Enumeration Documentation

◆ ExtAPIType

Enumeration of external API types.

Enumerator
UNCLASSIFIED 
MEMCPY 
MEMSET 
STRCPY 
STRCAT 

Definition at line 49 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:123
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:42
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition AbsExtAPI.h:124
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:125
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 307 of file AbsExtAPI.cpp.

308{
309 if (checkpoints.size() == 0)
310 {
311 return;
312 }
313 else
314 {
315 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
316 for (const CallICFGNode* call: checkpoints)
317 SVFUtil::errs() << call->toString() + "\n";
318 assert(false);
319 }
320}
Set< const CallICFGNode * > checkpoints
Definition AbsExtAPI.h:120
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 267 of file AbsExtAPI.cpp.

268{
269 // traverse every ICFGNode
270 Set<std::string> ae_checkpoint_names = {"svf_assert"};
271 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
272 Set<std::string> nullptr_checkpoint_names = {"UNSAFE_LOAD", "SAFE_LOAD"};
273
274 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
275 {
276 const ICFGNode* node = it->second;
277 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
278 {
279 if (const FunObjVar *fun = call->getCalledFunction())
280 {
281 if (ae_checkpoint_names.find(fun->getName()) !=
283 {
284 checkpoints.insert(call);
285 }
287 {
288 if (buf_checkpoint_names.find(fun->getName()) !=
290 {
291 checkpoints.insert(call);
292 }
293 }
295 {
296 if (nullptr_checkpoint_names.find(fun->getName()) !=
298 {
299 checkpoints.insert(call);
300 }
301 }
302 }
303 }
304 }
305}
iterator begin()
Iterators.
static const Option< bool > NullDerefCheck
nullptr dereference checker, Default: false
Definition Options.h:255
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:253

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

263{
264 return ae->getAbsState(node);
265}
AbstractState & getAbsState(const ICFGNode *node)

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

427{
428 if (var->getType()->isArrayTy())
429 {
430 return SVFUtil::dyn_cast<SVFArrayType>(var->getType())
431 ->getTypeOfElement()->getByteSize();
432 }
433 if (var->getType()->isPointerTy())
434 return 1;
435 assert(false && "unsupported type for element size");
436 return 1;
437}

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

643{
644 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
645 {
646 u32_t bits = type->getByteSize() * 8;
647 s64_t ub = 0;
648 s64_t lb = 0;
649 if (bits >= 32)
650 {
651 if (intType->isSigned())
652 {
653 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
654 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
655 }
656 else
657 {
658 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
659 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
660 }
661 }
662 else if (bits == 16)
663 {
664 if (intType->isSigned())
665 {
666 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
667 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
668 }
669 else
670 {
671 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
672 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
673 }
674 }
675 else if (bits == 8)
676 {
677 if (intType->isSigned())
678 {
679 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
680 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
681 }
682 else
683 {
684 ub = static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
685 lb = static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
686 }
687 }
688 return IntervalValue(lb, ub);
689 }
690 else if (SVFUtil::isa<SVFOtherType>(type))
691 {
692 // handle other type like float double, set s32_t as the range
693 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
694 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
695 return IntervalValue(lb, ub);
696 }
697 else
698 {
699 return IntervalValue::top();
700 // other types, return top interval
701 }
702}
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 450 of file AbsExtAPI.cpp.

451{
453 // Step 1: determine the buffer size (in bytes) backing this pointer
454 u32_t dst_size = 0;
455 const AbstractValue& ptrVal = ae->getAbsValue(strValue, node);
456 for (const auto& addr : ptrVal.getAddrs())
457 {
458 NodeID objId = as.getIDFromAddr(addr);
460 {
462 }
463 else
464 {
465 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
466 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
467 {
468 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
469 {
471 }
472 }
473 }
474 }
475
476 // Step 2: scan for '\0' terminator
477 u32_t len = 0;
478 if (ae->getAbsValue(strValue, node).isAddr())
479 {
480 for (u32_t index = 0; index < dst_size; index++)
481 {
485 for (const auto &addr: expr0.getAddrs())
486 {
487 val.join_with(as.load(addr));
488 }
489 if (val.getInterval().is_numeral() &&
490 (char) val.getInterval().getIntNumeral() == '\0')
491 {
492 break;
493 }
494 ++len;
495 }
496 }
497
498 // Step 3: scale by element size and return
500 if (len == 0)
502 return IntervalValue(len * elemSize);
503}
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.
u32_t getAllocaInstByteSize(const AddrStmt *addr)
AddressValue getGepObjAddrs(const ValVar *pointer, IntervalValue offset)
virtual const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node)
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 351 of file AbsExtAPI.cpp.

352{
353 const FunObjVar *fun = call->getCalledFunction();
354 assert(fun && "FunObjVar* is nullptr");
356 // get type of mem api
357 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
358 {
359 if (annotation.find("MEMCPY") != std::string::npos)
360 extType = MEMCPY;
361 if (annotation.find("MEMSET") != std::string::npos)
362 extType = MEMSET;
363 if (annotation.find("STRCPY") != std::string::npos)
364 extType = STRCPY;
365 if (annotation.find("STRCAT") != std::string::npos)
366 extType = STRCAT;
367 }
368 if (extType == UNCLASSIFIED)
369 {
370 if (func_map.find(fun->getName()) != func_map.end())
371 {
372 func_map[fun->getName()](call);
373 }
374 else
375 {
376 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
377 {
378 const AbstractValue& retVal = ae->getAbsValue(ret, call);
379 if (!retVal.isAddr())
380 {
381 ae->updateAbsValue(ret, IntervalValue(), call);
382 }
383 }
384 return;
385 }
386 }
387 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
388 else if (extType == MEMCPY)
389 {
390 IntervalValue len = ae->getAbsValue(call->getArgument(2), call).getInterval();
391 handleMemcpy(call->getArgument(0), call->getArgument(1), len, 0, call);
392 }
393 else if (extType == MEMSET)
394 {
397 handleMemset(call->getArgument(0), elem, len, call);
398 }
399 else if (extType == STRCPY)
400 {
401 handleStrcpy(call);
402 }
403 else if (extType == STRCAT)
404 {
405 // Both strcat and strncat are annotated as STRCAT.
406 // Distinguish by name: strncat/wcsncat contain "ncat".
407 const std::string& name = fun->getName();
408 if (name.find("ncat") != std::string::npos)
409 handleStrncat(call);
410 else
411 handleStrcat(call);
412 }
413 else
414 {
415
416 }
417 return;
418}
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:49
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:126
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: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 545 of file AbsExtAPI.cpp.

548{
549 if (!isValidLength(len)) return;
551
553 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
554 (u32_t)len.lb().getIntNumeral());
555 u32_t range_val = size / elemSize;
556
557 if (!ae->getAbsValue(src, node).isAddr() || !ae->getAbsValue(dst, node).isAddr())
558 return;
559
560 for (u32_t index = 0; index < range_val; index++)
561 {
566 for (const auto &dstAddr: expr_dst.getAddrs())
567 {
568 for (const auto &srcAddr: expr_src.getAddrs())
569 {
570 u32_t objId = as.getIDFromAddr(srcAddr);
571 if (as.inAddrToValTable(objId) || as.inAddrToAddrsTable(objId))
572 {
573 as.store(dstAddr, as.load(srcAddr));
574 }
575 }
576 }
577 }
578}
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 585 of file AbsExtAPI.cpp.

587{
588 if (!isValidLength(len)) return;
590
591 u32_t elemSize = 1;
592 if (dst->getType()->isArrayTy())
593 {
594 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())
595 ->getTypeOfElement()->getByteSize();
596 }
597 else if (dst->getType()->isPointerTy())
598 {
599 elemSize = 1;
600 }
601 else
602 {
603 assert(false && "unsupported type for element size");
604 }
605 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
606 (u32_t)len.lb().getIntNumeral());
607 u32_t range_val = size / elemSize;
608
609 for (u32_t index = 0; index < range_val; index++)
610 {
611 if (!ae->getAbsValue(dst, node).isAddr())
612 break;
614 for (const auto &addr: lhs_gep.getAddrs())
615 {
616 u32_t objId = as.getIDFromAddr(addr);
617 if (as.inAddrToValTable(objId))
618 {
619 AbstractValue tmp = as.load(addr);
621 as.store(addr, tmp);
622 }
623 else
624 {
625 as.store(addr, elem);
626 }
627 }
628 }
629}
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 522 of file AbsExtAPI.cpp.

523{
524 const ValVar* dst = call->getArgument(0);
525 const ValVar* src = call->getArgument(1);
526 IntervalValue dstLen = getStrlen(dst, call);
527 IntervalValue srcLen = getStrlen(src, call);
528 if (!isValidLength(dstLen)) return;
529 handleMemcpy(dst, src, srcLen, dstLen.lb().getIntNumeral(), call);
530}
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 511 of file AbsExtAPI.cpp.

512{
513 const ValVar* dst = call->getArgument(0);
514 const ValVar* src = call->getArgument(1);
515 IntervalValue srcLen = getStrlen(src, call);
516 if (!isValidLength(srcLen)) return;
517 handleMemcpy(dst, src, srcLen, 0, call);
518}

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

535{
536 const ValVar* dst = call->getArgument(0);
537 const ValVar* src = call->getArgument(1);
539 IntervalValue dstLen = getStrlen(dst, call);
540 if (!isValidLength(dstLen)) return;
541 handleMemcpy(dst, src, n, dstLen.lb().getIntNumeral(), call);
542}
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 = ae->getAbsValue(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 ae->updateAbsValue(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 = ae->getAbsValue(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 = ae->getAbsValue(callNode->getArgument(0), callNode);
97 const AbstractValue& arg1Val = ae->getAbsValue(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 = ae->getAbsValue(callNode->getArgument(1), callNode);
127 const AbstractValue& ubVal = ae->getAbsValue(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 ae->updateAbsValue(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_fread = [&](const CallICFGNode *callNode)
149 {
150 if (callNode->arg_size() < 3) return;
151 IntervalValue block_count = ae->getAbsValue(callNode->getArgument(2), callNode).getInterval();
152 IntervalValue block_size = ae->getAbsValue(callNode->getArgument(1), callNode).getInterval();
154 (void)block_byte;
155 };
156 func_map["fread"] = sse_fread;
157
158 auto sse_sprintf = [&](const CallICFGNode *callNode)
159 {
160 // printf is difficult to predict since it has no byte size arguments
161 };
162
163 auto sse_snprintf = [&](const CallICFGNode *callNode)
164 {
165 if (callNode->arg_size() < 2) return;
166 // get elem size of arg2
167 u32_t elemSize = 1;
168 if (callNode->getArgument(2)->getType()->isArrayTy())
169 {
170 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
171 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
172 }
173 else if (callNode->getArgument(2)->getType()->isPointerTy())
174 {
175 elemSize = 1;
176 }
177 else
178 {
179 return;
180 }
181 IntervalValue size = ae->getAbsValue(callNode->getArgument(1), callNode).getInterval()
183 (void)size;
184 };
185 func_map["__snprintf_chk"] = sse_snprintf;
186 func_map["__vsprintf_chk"] = sse_sprintf;
187 func_map["__sprintf_chk"] = sse_sprintf;
188 func_map["snprintf"] = sse_snprintf;
189 func_map["sprintf"] = sse_sprintf;
190 func_map["vsprintf"] = sse_sprintf;
191 func_map["vsnprintf"] = sse_snprintf;
192 func_map["__vsnprintf_chk"] = sse_snprintf;
193 func_map["swprintf"] = sse_snprintf;
194 func_map["_snwprintf"] = sse_snprintf;
195
196
197 auto sse_itoa = [&](const CallICFGNode* callNode)
198 {
199 if (callNode->arg_size() < 3) return;
200 u32_t num = (u32_t) ae->getAbsValue(callNode->getArgument(0), callNode).getInterval().getNumeral();
201 std::string snum = std::to_string(num);
202 (void)snum;
203 };
204 func_map["itoa"] = sse_itoa;
205
206
207 auto sse_strlen = [&](const CallICFGNode *callNode)
208 {
209 if (callNode->arg_size() < 1) return;
210 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
211 IntervalValue byteLen = getStrlen(callNode->getArgument(0), callNode);
212 u32_t elemSize = getElementSize(callNode->getArgument(0));
213 if (byteLen.is_numeral() && elemSize > 1)
215 else
217 };
218 func_map["strlen"] = sse_strlen;
219 func_map["wcslen"] = sse_strlen;
220
221 auto sse_recv = [&](const CallICFGNode *callNode)
222 {
223 if (callNode->arg_size() < 4) return;
224 IntervalValue len = ae->getAbsValue(callNode->getArgument(2), callNode).getInterval() - IntervalValue(1);
225 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
227 };
228 func_map["recv"] = sse_recv;
229 func_map["__recv"] = sse_recv;
230
231 auto sse_free = [&](const CallICFGNode *callNode)
232 {
233 if (callNode->arg_size() < 1) return;
235 const AbstractValue& ptrVal = ae->getAbsValue(callNode->getArgument(0), callNode);
236 for (auto addr: ptrVal.getAddrs())
237 {
239 {
240 }
241 else
242 {
243 as.addToFreedAddrs(addr);
244 }
245 }
246 };
247 // Add all free-related functions to func_map
248 std::vector<std::string> freeFunctions =
249 {
250 "VOS_MemFree", "cfree", "free", "free_all_mem", "freeaddrinfo",
251 "gcry_mpi_release", "gcry_sexp_release", "globfree", "nhfree",
252 "obstack_free", "safe_cfree", "safe_free", "safefree", "safexfree",
253 "sm_free", "vim_free", "xfree", "SSL_CTX_free", "SSL_free", "XFree"
254 };
255
256 for (const auto& name : freeFunctions)
257 {
259 }
260};
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(const ValVar *rhs, const ICFGNode *node)
Reads a string from the abstract state.
static bool isBlackHoleObjAddr(u32_t addr)
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:969
int isdigit(int c)
Definition extapi.c:974
int isgraph(int c)
Definition extapi.c:979
int isspace(char c)
Definition extapi.c:999
int isprint(int c)
Definition extapi.c:989
int ispunct(int argument)
Definition extapi.c:994
int isblank(int character)
Definition extapi.c:964
int isalnum(int character)
Definition extapi.c:954
int isupper(int c)
Definition extapi.c:1004
int isxdigit(int c)
Definition extapi.c:1009
int isalpha(int character)
Definition extapi.c:959
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 442 of file AbsExtAPI.cpp.

443{
444 return !len.isBottom() && !len.lb().is_minus_infinity();
445}

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

323{
325 std::string str0;
326
328 {
329 if (!ae->getAbsValue(rhs, node).isAddr()) continue;
332
334 for (const auto &addr: expr0.getAddrs())
335 {
336 val.join_with(as.load(addr));
337 }
338 if (!val.getInterval().is_numeral())
339 {
340 break;
341 }
342 if ((char) val.getInterval().getIntNumeral() == '\0')
343 {
344 break;
345 }
346 str0.push_back((char) val.getInterval().getIntNumeral());
347 }
348 return str0;
349}

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 55 of file AbsExtAPI.h.

Member Data Documentation

◆ ae

AbstractInterpretation* SVF::AbsExtAPI::ae
protected

Owning AbstractInterpretation; provides state access.

Definition at line 123 of file AbsExtAPI.h.

◆ checkpoints

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

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

◆ icfg

ICFG* SVF::AbsExtAPI::icfg
protected

Pointer to the interprocedural control flow graph.

Definition at line 125 of file AbsExtAPI.h.

◆ svfir

SVFIR* SVF::AbsExtAPI::svfir
protected

Pointer to the SVF intermediate representation.

Definition at line 124 of file AbsExtAPI.h.


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