21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Support/raw_ostream.h"
24 using namespace clang;
28 class DereferenceChecker
29 :
public Checker< check::Location,
31 EventDispatcher<ImplicitNullDerefEvent> > {
32 mutable std::unique_ptr<BuiltinBug> BT_null;
33 mutable std::unique_ptr<BuiltinBug> BT_undef;
36 bool IsBind =
false)
const;
39 void checkLocation(
SVal location,
bool isLoad,
const Stmt*
S,
43 static void AddDerefSource(raw_ostream &os,
47 bool loadedFrom =
false);
52 DereferenceChecker::AddDerefSource(raw_ostream &os,
59 switch (Ex->getStmtClass()) {
62 case Stmt::DeclRefExprClass: {
65 os <<
" (" << (loadedFrom ?
"loaded from" :
"from")
66 <<
" variable '" << VD->getName() <<
"')";
67 Ranges.push_back(DR->getSourceRange());
71 case Stmt::MemberExprClass: {
73 os <<
" (" << (loadedFrom ?
"loaded from" :
"via")
79 case Stmt::ObjCIvarRefExprClass: {
81 os <<
" (" << (loadedFrom ?
"loaded from" :
"via")
100 BT_null.reset(
new BuiltinBug(
this,
"Dereference of null pointer"));
103 llvm::raw_svector_ostream os(buf);
109 if (
const Expr *
expr = dyn_cast<Expr>(S))
110 S =
expr->IgnoreParenLValueCasts();
114 if (BO->isAssignmentOp())
116 }
else if (
const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
117 assert(DS->isSingleDecl() &&
"We process decls one by one");
118 if (
const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
119 if (
const Expr *Init = VD->getAnyInitializer())
124 switch (S->getStmtClass()) {
125 case Stmt::ArraySubscriptExprClass: {
126 os <<
"Array access";
130 os <<
" results in a null pointer dereference";
133 case Stmt::UnaryOperatorClass: {
134 os <<
"Dereference of null pointer";
140 case Stmt::MemberExprClass: {
144 <<
"' results in a dereference of a null pointer";
150 case Stmt::ObjCIvarRefExprClass: {
152 os <<
"Access to instance variable '" << *IV->
getDecl()
153 <<
"' results in a dereference of a null pointer";
163 auto report = llvm::make_unique<BugReport>(
164 *BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N);
169 I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
170 report->addRange(*I);
175 void DereferenceChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt* S,
182 new BuiltinBug(
this,
"Dereference of undefined pointer value"));
185 llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
202 std::tie(notNullState, nullState) = state->assume(location);
207 reportBug(nullState, S, C);
216 dispatchEvent(event);
224 void DereferenceChecker::checkBind(
SVal L,
SVal V,
const Stmt *S,
245 reportBug(StNull, S, C,
true);
254 dispatchEvent(event);
const Expr * getBase() const
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
TypedValueRegion - An abstract class representing regions having a typed value.
const Expr * getDerefExpr(const Stmt *S)
StringRef getName() const
MemRegion - The root abstract class for all memory regions.
SourceLocation getLocation() const
DeclarationNameInfo getMemberNameInfo() const
Retrieve the member declaration name info.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
virtual QualType getValueType() const =0
bool isReferenceType() const
BugReporter & getBugReporter()
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
We dereferenced a location that may be null.
const LocationContext * getLocationContext() const
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Expr * getSubExpr() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
bool isDeclRefExprToReference(const Expr *E)
const MemRegion * getAsRegion() const
SourceLocation getMemberLoc() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
ObjCIvarRefExpr - A reference to an ObjC instance variable.
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
A trivial tuple used to represent a source range.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Expr * IgnoreParens() LLVM_READONLY