23#include "llvm/ADT/SmallString.h"
24#include "llvm/Support/raw_ostream.h"
30class DereferenceChecker
31 :
public Checker< check::Location,
33 EventDispatcher<ImplicitNullDerefEvent> > {
34 enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel };
37 BugType BT_Undef{
this,
"Dereference of undefined pointer value",
39 BugType BT_Label{
this,
"Dereference of the address of a label",
48 void checkLocation(
SVal location,
bool isLoad,
const Stmt* S,
52 static void AddDerefSource(raw_ostream &os,
56 bool loadedFrom =
false);
58 bool SuppressAddressSpaces =
false;
63DereferenceChecker::AddDerefSource(raw_ostream &os,
73 case Stmt::DeclRefExprClass: {
76 os <<
" (" << (loadedFrom ?
"loaded from" :
"from")
77 <<
" variable '" << VD->getName() <<
"')";
82 case Stmt::MemberExprClass: {
84 os <<
" (" << (loadedFrom ?
"loaded from" :
"via")
90 case Stmt::ObjCIvarRefExprClass: {
92 os <<
" (" << (loadedFrom ?
"loaded from" :
"via")
102 const Expr *
E =
nullptr;
106 if (
const Expr *
expr = dyn_cast<Expr>(S))
107 E =
expr->IgnoreParenLValueCasts();
120 const Expr *
E)
const {
133 if (SuppressAddressSpaces)
136 const llvm::Triple::ArchType Arch =
137 C.getASTContext().getTargetInfo().getTriple().getArch();
139 if ((Arch == llvm::Triple::x86) || (Arch == llvm::Triple::x86_64)) {
151 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
152 return DRE->getDecl()->getType()->isReferenceType();
159 llvm::StringRef DerefStr1;
160 llvm::StringRef DerefStr2;
162 case DerefKind::NullPointer:
164 DerefStr1 =
" results in a null pointer dereference";
165 DerefStr2 =
" results in a dereference of a null pointer";
167 case DerefKind::UndefinedPointerValue:
169 DerefStr1 =
" results in an undefined pointer dereference";
170 DerefStr2 =
" results in a dereference of an undefined pointer value";
172 case DerefKind::AddressOfLabel:
174 DerefStr1 =
" results in an undefined pointer dereference";
175 DerefStr2 =
" results in a dereference of an address of a label";
185 llvm::raw_svector_ostream os(buf);
189 switch (S->getStmtClass()) {
190 case Stmt::ArraySubscriptExprClass: {
191 os <<
"Array access";
198 case Stmt::ArraySectionExprClass: {
199 os <<
"Array access";
206 case Stmt::UnaryOperatorClass: {
209 AddDerefSource(os, Ranges,
U->getSubExpr()->IgnoreParens(),
213 case Stmt::MemberExprClass: {
222 case Stmt::ObjCIvarRefExprClass: {
224 os <<
"Access to instance variable '" << *IV->
getDecl() <<
"'" << DerefStr2;
233 auto report = std::make_unique<PathSensitiveBugReport>(
239 I = Ranges.begin(),
E = Ranges.end(); I!=
E; ++I)
240 report->addRange(*I);
242 C.emitReport(std::move(report));
245void DereferenceChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt* S,
250 if (!suppressReport(
C, DerefExpr))
251 reportBug(DerefKind::UndefinedPointerValue,
C.getState(), DerefExpr,
C);
258 if (!isa<Loc>(location))
264 std::tie(notNullState, nullState) = state->assume(location);
271 if (!suppressReport(
C,
expr)) {
272 reportBug(DerefKind::NullPointer, nullState,
expr,
C);
280 if (
ExplodedNode *N =
C.generateSink(nullState,
C.getPredecessor())) {
283 dispatchEvent(event);
288 C.addTransition(notNullState);
291void DereferenceChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
299 reportBug(DerefKind::AddressOfLabel,
C.getState(), S,
C);
319 if (!suppressReport(
C,
expr)) {
320 reportBug(DerefKind::NullPointer, StNull,
expr,
C);
327 if (
ExplodedNode *N =
C.generateSink(StNull,
C.getPredecessor())) {
331 dispatchEvent(event);
351 C.addTransition(State,
this);
360bool ento::shouldRegisterDereferenceChecker(
const CheckerManager &mgr) {
static const Expr * getDereferenceExpr(const Stmt *S, bool IsBind=false)
static bool isDeclRefExprToReference(const Expr *E)
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Expr * getBase()
Get base of the array section.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
A reference to a declared variable, function, enum, etc.
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'.
DeclarationNameInfo getMemberNameInfo() const
Retrieve the member declaration name info.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceLocation getLocation() const
const Expr * getBase() const
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isReferenceType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represents a variable declaration or definition.
StringRef getDescription() const
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
CheckerNameRef getCurrentCheckerName() const
const LocationContext * getLocationContext() const
MemRegion - The root abstract class for all memory regions.
ProgramState - This class encapsulates:
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const Expr * getDerefExpr(const Stmt *S)
Given that expression S represents a pointer that would be dereferenced, try to find a sub-expression...
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const LogicError
std::pair< const clang::VarDecl *, const clang::Expr * > parseAssignment(const Stmt *S)
The JSON file list parser is used to communicate input to InstallAPI.
unsigned toTargetAddressSpace(LangAS AS)
We dereferenced a location that may be null.