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 348 of file AEDetector.h.

Constructor & Destructor Documentation

◆ NullptrDerefDetector()

SVF::NullptrDerefDetector::NullptrDerefDetector ( )
inline

Definition at line 352 of file AEDetector.h.

353 {
355 }
@ 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 394 of file AEDetector.h.

395 {
398 eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
399
400 if (eventStack.empty())
401 {
402 return; // If the event stack is empty, return early
403 }
404 std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
405
406 // Check if the bug at this location has already been reported
407 if (bugLoc.find(loc) != bugLoc.end())
408 {
409 return; // If the bug location is already reported, return early
410 }
411 else
412 {
413 bugLoc.insert(loc); // Otherwise, mark this location as reported
414 }
416 nodeToBugInfo[node] = e.what(); // Record the exception information for the node
417 }
std::vector< SVFBugEvent > EventStack
Set< std::string > bugLoc
Set of locations where bugs have been reported.
Definition AEDetector.h:457
SVFBugReport recoder
Recorder for abstract execution bugs.
Definition AEDetector.h:458
Map< const ICFGNode *, std::string > nodeToBugInfo
Maps ICFG nodes to bug information.
Definition AEDetector.h:459
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 691 of file AEDetector.cpp.

692{
694 const AbstractValue& AbsVal = ae.getAbsValue(value, node);
695 if (isUninit(AbsVal)) return false;
696 if (!AbsVal.isAddr()) return true;
697 for (const auto &addr: AbsVal.getAddrs())
698 {
699 // Unknown, null, and freed addresses cannot be safely dereferenced.
701 ae.getAbsState(node).isFreedMem(addr))
702 return false;
703 }
704 return true;
705}
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:382

◆ classof()

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

Definition at line 359 of file AEDetector.h.

360 {
361 return detector->getKind() == AEDetector::NULL_DEREF;
362 }

◆ 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 536 of file AEDetector.cpp.

537{
538 if (SVFUtil::isa<CallICFGNode>(node))
539 {
540 // external API like memset(*dst, elem, sz)
541 // we check if it's external api and check the corrisponding index
542 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
543 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
544 {
546 }
547 }
548 else
549 {
550 for (const auto& stmt: node->getSVFStmts())
551 {
552 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
553 {
554 // like llvm bitcode `p = gep p, idx`
555 // we check rhs p's all address are valid mem
556 const ValVar* rhs = gep->getRHSVar();
557 if (!canSafelyDerefPtr(rhs, node))
558 {
559 AEException bug(stmt->toString());
560 addBugToReporter(bug, stmt->getICFGNode());
561 }
562 }
563 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
564 {
565 // like llvm bitcode `p = load q`
566 // we check lhs p's all address are valid mem
567 const ValVar* lhs = load->getLHSVar();
568 if (!canSafelyDerefPtr(lhs, node))
569 {
570 AEException bug(stmt->toString());
571 addBugToReporter(bug, stmt->getICFGNode());
572 }
573 }
574 }
575 }
576}
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:394
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 632 of file AEDetector.cpp.

633{
634 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
635 // get ext type
636 // get argument index which are nullptr deref checkpoints for extapi
637 std::vector<u32_t> tmp_args;
638 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
639 {
640 if (annotation.find("MEMCPY") != std::string::npos)
641 {
642 if (call->arg_size() < 4)
643 {
644 // for memcpy(void* dest, const void* src, size_t n)
645 tmp_args.push_back(0);
646 tmp_args.push_back(1);
647 }
648 else
649 {
650 // for unsigned long iconv(void* cd, char **restrict inbuf, unsigned long *restrict inbytesleft, char **restrict outbuf, unsigned long *restrict outbytesleft)
651 tmp_args.push_back(1);
652 tmp_args.push_back(2);
653 tmp_args.push_back(3);
654 tmp_args.push_back(4);
655 }
656 }
657 else if (annotation.find("MEMSET") != std::string::npos)
658 {
659 // for memset(void* dest, elem, sz)
660 tmp_args.push_back(0);
661 }
662 else if (annotation.find("STRCPY") != std::string::npos)
663 {
664 // for strcpy(void* dest, void* src)
665 tmp_args.push_back(0);
666 tmp_args.push_back(1);
667 }
668 else if (annotation.find("STRCAT") != std::string::npos)
669 {
670 // for strcat(void* dest, const void* src)
671 // for strncat(void* dest, const void* src, size_t n)
672 tmp_args.push_back(0);
673 tmp_args.push_back(1);
674 }
675 }
676
677 for (const auto &arg: tmp_args)
678 {
679 if (call->arg_size() <= arg)
680 continue;
681 const ValVar* argVal = call->getArgument(arg);
682 if (argVal && !canSafelyDerefPtr(argVal, call))
683 {
684 AEException bug(call->toString());
685 addBugToReporter(bug, call);
686 }
687 }
688}
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 579 of file AEDetector.cpp.

580{
581 std::string funcName = callNode->getCalledFunction()->getName();
583 if (funcName == "UNSAFE_LOAD")
584 {
585 // void UNSAFE_LOAD(void* ptr);
586 ae.getUtils()->checkpoints.erase(callNode);
587 if (callNode->arg_size() < 1)
588 return;
589
590 const ValVar* arg0Val = callNode->getArgument(0);
591 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)
593 SVFUtil::outs() << "[UNSAFE_LOAD] node=" << callNode->getId()
594 << " arg0=" << arg0Val->getId() << " isSafe=" << isSafe
595 << "\n";
596 if (!isSafe)
597 {
598 SVFUtil::outs() << SVFUtil::sucMsg("success: expected null dereference at UNSAFE_LOAD")
599 << " — " << callNode->toString() << "\n";
600 return;
601 }
602 else
603 {
604 SVFUtil::outs() << SVFUtil::errMsg("failure: null dereference expected at UNSAFE_LOAD, but none detected")
605 << " — Position: " << callNode->getSourceLoc() << "\n";
606 assert(false);
607 }
608 }
609 else if (funcName == "SAFE_LOAD")
610 {
611 // void SAFE_LOAD(void* ptr);
612 ae.getUtils()->checkpoints.erase(callNode);
613 if (callNode->arg_size() < 1) return;
614 const ValVar* arg0Val = callNode->getArgument(0);
615 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)ols
617 if (isSafe)
618 {
619 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe dereference at SAFE_LOAD")
620 << " — " << callNode->toString() << "\n";
621 return;
622 }
623 else
624 {
625 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected null dereference at SAFE_LOAD")
626 << " — Position: " << callNode->getSourceLoc() << "\n";
627 assert(false);
628 }
629 }
630}
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 449 of file AEDetector.h.

450 {
451 return !v.isAddr() && !v.isInterval();
452 }

◆ 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 382 of file AEDetector.h.

383 {
384 // uninitialized value has neither interval value nor address value
385 bool is = v.getAddrs().isBottom() && v.getInterval().isBottom();
386 return is;
387 }

◆ reportBug()

void SVF::NullptrDerefDetector::reportBug ( )
inlineoverridevirtual

Reports all detected nullptr dereference bugs.

Implements SVF::AEDetector.

Definition at line 422 of file AEDetector.h.

423 {
424 if (!nodeToBugInfo.empty())
425 {
426 std::cerr << "###################### Nullptr Dereference (" + std::to_string(nodeToBugInfo.size())
427 + " found)######################\n";
428 std::cerr << "---------------------------------------------\n";
429 for (const auto& it : nodeToBugInfo)
430 {
431 std::cerr << it.second << "\n---------------------------------------------\n";
432 }
433 }
434 }

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 350 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 457 of file AEDetector.h.

◆ nodeToBugInfo

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

Maps ICFG nodes to bug information.

Definition at line 459 of file AEDetector.h.

◆ recoder

SVFBugReport SVF::NullptrDerefDetector::recoder
private

Recorder for abstract execution bugs.

Definition at line 458 of file AEDetector.h.


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