Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Attributes | Friends | List of all members
SVF::NullptrDerefDetector Class Reference

#include <AEDetector.h>

Inheritance diagram for SVF::NullptrDerefDetector:
SVF::AEDetector

Public Member Functions

 NullptrDerefDetector ()
 
 ~NullptrDerefDetector ()=default
 
void detect (const ICFGNode *node) override
 Detects nullptr dereferences issues within a node.
 
void handleStubFunctions (const CallICFGNode *call) override
 Handles external API calls related to nullptr dereferences.
 
bool isUninit (AbstractValue v)
 Checks if an Abstract Value is uninitialized.
 
void addBugToReporter (const AEException &e, const ICFGNode *node)
 Adds a bug to the reporter based on an exception.
 
void reportBug () override
 Reports all detected nullptr dereference bugs.
 
void detectExtAPI (const CallICFGNode *call)
 Handle external API calls related to nullptr dereferences.
 
bool isNull (AbstractValue v)
 Check if an Abstract Value is NULL (or uninitialized).
 
bool canSafelyDerefPtr (const ValVar *ptr, const ICFGNode *node)
 
- Public Member Functions inherited from SVF::AEDetector
 AEDetector ()
 Constructor initializes the detector kind to UNKNOWN.
 
virtual ~AEDetector ()=default
 Virtual destructor for safe polymorphic use.
 
DetectorKind getKind () const
 Get the kind of the detector.
 

Static Public Member Functions

static bool classof (const AEDetector *detector)
 
- Static Public Member Functions inherited from SVF::AEDetector
static bool classof (const AEDetector *detector)
 Check if the detector is of the UNKNOWN kind.
 

Private Attributes

Set< std::string > bugLoc
 Set of locations where bugs have been reported.
 
SVFBugReport recoder
 Recorder for abstract execution bugs.
 
Map< const ICFGNode *, std::string > nodeToBugInfo
 Maps ICFG nodes to bug information.
 

Friends

class AbstractInterpretation
 

Additional Inherited Members

- Public Types inherited from SVF::AEDetector
enum  DetectorKind { BUF_OVERFLOW , NULL_DEREF , UNKNOWN }
 Enumerates the types of detectors available. More...
 
- Protected Attributes inherited from SVF::AEDetector
DetectorKind kind
 The kind of the detector.
 

Detailed Description

Definition at line 331 of file AEDetector.h.

Constructor & Destructor Documentation

◆ NullptrDerefDetector()

SVF::NullptrDerefDetector::NullptrDerefDetector ( )
inline

Definition at line 335 of file AEDetector.h.

336 {
338 }
@ NULL_DEREF
Detector for nullptr dereference issues.
Definition AEDetector.h:52
DetectorKind kind
The kind of the detector.
Definition AEDetector.h:104

◆ ~NullptrDerefDetector()

SVF::NullptrDerefDetector::~NullptrDerefDetector ( )
default

Member Function Documentation

◆ addBugToReporter()

void SVF::NullptrDerefDetector::addBugToReporter ( const AEException &  e,
const ICFGNode *  node 
)
inline

Adds a bug to the reporter based on an exception.

Parameters
eThe exception that was thrown.
nodePointer to the ICFG node where the bug was detected.

Definition at line 377 of file AEDetector.h.

378 {
381 eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
382
383 if (eventStack.empty())
384 {
385 return; // If the event stack is empty, return early
386 }
387 std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
388
389 // Check if the bug at this location has already been reported
390 if (bugLoc.find(loc) != bugLoc.end())
391 {
392 return; // If the bug location is already reported, return early
393 }
394 else
395 {
396 bugLoc.insert(loc); // Otherwise, mark this location as reported
397 }
399 nodeToBugInfo[node] = e.what(); // Record the exception information for the node
400 }
std::vector< SVFBugEvent > EventStack
Set< std::string > bugLoc
Set of locations where bugs have been reported.
Definition AEDetector.h:440
SVFBugReport recoder
Recorder for abstract execution bugs.
Definition AEDetector.h:441
Map< const ICFGNode *, std::string > nodeToBugInfo
Maps ICFG nodes to bug information.
Definition AEDetector.h:442
void addAbsExecBug(GenericBug::BugType bugType, const GenericBug::EventStack &eventStack, s64_t allocLowerBound, s64_t allocUpperBound, s64_t accessLowerBound, s64_t accessUpperBound)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ canSafelyDerefPtr()

bool NullptrDerefDetector::canSafelyDerefPtr ( const ValVar *  ptr,
const ICFGNode *  node 
)

Definition at line 678 of file AEDetector.cpp.

679{
681 const AbstractValue& AbsVal = ae.getAbsValue(value, node);
682 if (isUninit(AbsVal)) return false;
683 if (!AbsVal.isAddr()) return true;
684 for (const auto &addr: AbsVal.getAddrs())
685 {
686 // Unknown, null, and freed addresses cannot be safely dereferenced.
688 ae.getAbsState(node).isFreedMem(addr))
689 return false;
690 }
691 return true;
692}
static AbstractInterpretation & getAEInstance()
static bool isNullOrBlackHoleAddr(u32_t addr)
Whether addr has no concrete backing memory object.
bool isUninit(AbstractValue v)
Checks if an Abstract Value is uninitialized.
Definition AEDetector.h:365

◆ classof()

static bool SVF::NullptrDerefDetector::classof ( const AEDetector *  detector)
inlinestatic

Definition at line 342 of file AEDetector.h.

343 {
344 return detector->getKind() == AEDetector::NULL_DEREF;
345 }

◆ detect()

void NullptrDerefDetector::detect ( const ICFGNode *  node)
overridevirtual

Detects nullptr dereferences issues within a node.

Parameters
asReference to the abstract state.
nodePointer to the ICFG node.

Implements SVF::AEDetector.

Definition at line 523 of file AEDetector.cpp.

524{
525 if (SVFUtil::isa<CallICFGNode>(node))
526 {
527 // external API like memset(*dst, elem, sz)
528 // we check if it's external api and check the corrisponding index
529 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
530 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
531 {
533 }
534 }
535 else
536 {
537 for (const auto& stmt: node->getSVFStmts())
538 {
539 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
540 {
541 // like llvm bitcode `p = gep p, idx`
542 // we check rhs p's all address are valid mem
543 const ValVar* rhs = gep->getRHSVar();
544 if (!canSafelyDerefPtr(rhs, node))
545 {
546 AEException bug(stmt->toString());
547 addBugToReporter(bug, stmt->getICFGNode());
548 }
549 }
550 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
551 {
552 // like llvm bitcode `p = load q`
553 // we check lhs p's all address are valid mem
554 const ValVar* lhs = load->getLHSVar();
555 if (!canSafelyDerefPtr(lhs, node))
556 {
557 AEException bug(stmt->toString());
558 addBugToReporter(bug, stmt->getICFGNode());
559 }
560 }
561 }
562 }
563}
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:112
bool canSafelyDerefPtr(const ValVar *ptr, const ICFGNode *node)
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:377
void detectExtAPI(const CallICFGNode *call)
Handle external API calls related to nullptr dereferences.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:526

◆ detectExtAPI()

void NullptrDerefDetector::detectExtAPI ( const CallICFGNode *  call)

Handle external API calls related to nullptr dereferences.

Parameters
asReference to the abstract state.
callPointer to the call ICFG node.

Definition at line 619 of file AEDetector.cpp.

620{
621 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
622 // get ext type
623 // get argument index which are nullptr deref checkpoints for extapi
624 std::vector<u32_t> tmp_args;
625 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
626 {
627 if (annotation.find("MEMCPY") != std::string::npos)
628 {
629 if (call->arg_size() < 4)
630 {
631 // for memcpy(void* dest, const void* src, size_t n)
632 tmp_args.push_back(0);
633 tmp_args.push_back(1);
634 }
635 else
636 {
637 // for unsigned long iconv(void* cd, char **restrict inbuf, unsigned long *restrict inbytesleft, char **restrict outbuf, unsigned long *restrict outbytesleft)
638 tmp_args.push_back(1);
639 tmp_args.push_back(2);
640 tmp_args.push_back(3);
641 tmp_args.push_back(4);
642 }
643 }
644 else if (annotation.find("MEMSET") != std::string::npos)
645 {
646 // for memset(void* dest, elem, sz)
647 tmp_args.push_back(0);
648 }
649 else if (annotation.find("STRCPY") != std::string::npos)
650 {
651 // for strcpy(void* dest, void* src)
652 tmp_args.push_back(0);
653 tmp_args.push_back(1);
654 }
655 else if (annotation.find("STRCAT") != std::string::npos)
656 {
657 // for strcat(void* dest, const void* src)
658 // for strncat(void* dest, const void* src, size_t n)
659 tmp_args.push_back(0);
660 tmp_args.push_back(1);
661 }
662 }
663
664 for (const auto &arg: tmp_args)
665 {
666 if (call->arg_size() <= arg)
667 continue;
668 const ValVar* argVal = call->getArgument(arg);
669 if (argVal && !canSafelyDerefPtr(argVal, call))
670 {
671 AEException bug(call->toString());
672 addBugToReporter(bug, call);
673 }
674 }
675}
const std::string toString() const override
Definition ICFG.cpp:129
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:483
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:501
u32_t arg_size() const
Definition ICFGNode.h:488

◆ handleStubFunctions()

void NullptrDerefDetector::handleStubFunctions ( const CallICFGNode *  call)
overridevirtual

Handles external API calls related to nullptr dereferences.

Parameters
callPointer to the call ICFG node.

Implements SVF::AEDetector.

Definition at line 566 of file AEDetector.cpp.

567{
568 std::string funcName = callNode->getCalledFunction()->getName();
570 if (funcName == "UNSAFE_LOAD")
571 {
572 // void UNSAFE_LOAD(void* ptr);
573 ae.getUtils()->checkpoints.erase(callNode);
574 if (callNode->arg_size() < 1)
575 return;
576
577 const ValVar* arg0Val = callNode->getArgument(0);
578 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)
580 SVFUtil::outs() << "[UNSAFE_LOAD] node=" << callNode->getId()
581 << " arg0=" << arg0Val->getId() << " isSafe=" << isSafe
582 << "\n";
583 if (!isSafe)
584 {
585 SVFUtil::outs() << SVFUtil::sucMsg("success: expected null dereference at UNSAFE_LOAD")
586 << " — " << callNode->toString() << "\n";
587 return;
588 }
589 else
590 {
591 SVFUtil::outs() << SVFUtil::errMsg("failure: null dereference expected at UNSAFE_LOAD, but none detected")
592 << " — Position: " << callNode->getSourceLoc() << "\n";
593 assert(false);
594 }
595 }
596 else if (funcName == "SAFE_LOAD")
597 {
598 // void SAFE_LOAD(void* ptr);
599 ae.getUtils()->checkpoints.erase(callNode);
600 if (callNode->arg_size() < 1) return;
601 const ValVar* arg0Val = callNode->getArgument(0);
602 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)ols
604 if (isSafe)
605 {
606 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe dereference at SAFE_LOAD")
607 << " — " << callNode->toString() << "\n";
608 return;
609 }
610 else
611 {
612 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected null dereference at SAFE_LOAD")
613 << " — Position: " << callNode->getSourceLoc() << "\n";
614 assert(false);
615 }
616 }
617}
NodeID getId() const
Get ID.
Definition SVFValue.h:158
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:75
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:98
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58

◆ isNull()

bool SVF::NullptrDerefDetector::isNull ( AbstractValue  v)
inline

Check if an Abstract Value is NULL (or uninitialized).

Parameters
vAn Abstract Value of loaded from an address in an Abstract State.

Definition at line 432 of file AEDetector.h.

433 {
434 return !v.isAddr() && !v.isInterval();
435 }

◆ isUninit()

bool SVF::NullptrDerefDetector::isUninit ( AbstractValue  v)
inline

Checks if an Abstract Value is uninitialized.

Parameters
vThe Abstract Value to check.
Returns
True if the value is uninitialized, false otherwise.

Definition at line 365 of file AEDetector.h.

366 {
367 // uninitialized value has neither interval value nor address value
368 bool is = v.getAddrs().isBottom() && v.getInterval().isBottom();
369 return is;
370 }

◆ reportBug()

void SVF::NullptrDerefDetector::reportBug ( )
inlineoverridevirtual

Reports all detected nullptr dereference bugs.

Implements SVF::AEDetector.

Definition at line 405 of file AEDetector.h.

406 {
407 if (!nodeToBugInfo.empty())
408 {
409 std::cerr << "###################### Nullptr Dereference (" + std::to_string(nodeToBugInfo.size())
410 + " found)######################\n";
411 std::cerr << "---------------------------------------------\n";
412 for (const auto& it : nodeToBugInfo)
413 {
414 std::cerr << it.second << "\n---------------------------------------------\n";
415 }
416 }
417 }

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 333 of file AEDetector.h.

Member Data Documentation

◆ bugLoc

Set<std::string> SVF::NullptrDerefDetector::bugLoc
private

Set of locations where bugs have been reported.

Definition at line 440 of file AEDetector.h.

◆ nodeToBugInfo

Map<const ICFGNode*, std::string> SVF::NullptrDerefDetector::nodeToBugInfo
private

Maps ICFG nodes to bug information.

Definition at line 442 of file AEDetector.h.

◆ recoder

SVFBugReport SVF::NullptrDerefDetector::recoder
private

Recorder for abstract execution bugs.

Definition at line 441 of file AEDetector.h.


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