diff options
-rw-r--r-- | lib/Checker/DereferenceChecker.cpp | 55 | ||||
-rw-r--r-- | test/Analysis/inline.c | 2 | ||||
-rw-r--r-- | test/Analysis/null-deref-ps.c | 4 | ||||
-rw-r--r-- | test/Analysis/plist-output.m | 40 |
4 files changed, 61 insertions, 40 deletions
diff --git a/lib/Checker/DereferenceChecker.cpp b/lib/Checker/DereferenceChecker.cpp index 0cbc408670..dfd3b61b0a 100644 --- a/lib/Checker/DereferenceChecker.cpp +++ b/lib/Checker/DereferenceChecker.cpp @@ -29,9 +29,9 @@ public: DereferenceChecker() : BT_null(0), BT_undef(0) {} static void *getTag() { static int tag = 0; return &tag; } void VisitLocation(CheckerContext &C, const Stmt *S, SVal location); - + std::pair<ExplodedNode * const*, ExplodedNode * const*> - getImplicitNodes() const { + getImplicitNodes() const { return std::make_pair(ImplicitNullDerefNodes.data(), ImplicitNullDerefNodes.data() + ImplicitNullDerefNodes.size()); @@ -59,7 +59,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, if (ExplodedNode *N = C.GenerateSink()) { if (!BT_undef) BT_undef = new BuiltinBug("Dereference of undefined pointer value"); - + EnhancedBugReport *report = new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N); report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, @@ -68,31 +68,32 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, } return; } - + DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l); - - // Check for null dereferences. + + // Check for null dereferences. if (!isa<Loc>(location)) return; - + const GRState *state = C.getState(); const GRState *notNullState, *nullState; llvm::tie(notNullState, nullState) = state->Assume(location); - + // The explicit NULL case. if (nullState) { - if (!notNullState) { + if (!notNullState) { // Generate an error node. ExplodedNode *N = C.GenerateSink(nullState); if (!N) return; - + // We know that 'location' cannot be non-null. This is what - // we call an "explicit" null dereference. + // we call an "explicit" null dereference. if (!BT_null) BT_null = new BuiltinBug("Dereference of null pointer"); - + llvm::SmallString<100> buf; + llvm::SmallVector<SourceRange, 2> Ranges; switch (S->getStmtClass()) { case Stmt::UnaryOperatorClass: { @@ -101,10 +102,26 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(SU)) { if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { llvm::raw_svector_ostream os(buf); - os << "Dereference of null pointer loaded from variable '" - << VD->getName() << '\''; + os << "Dereference of null pointer (loaded from variable '" + << VD->getName() << "')"; + Ranges.push_back(DR->getSourceRange()); } } + break; + } + case Stmt::MemberExprClass: { + const MemberExpr *M = cast<MemberExpr>(S); + if (M->isArrow()) + if (DeclRefExpr *DR = + dyn_cast<DeclRefExpr>(M->getBase()->IgnoreParenCasts())) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { + llvm::raw_svector_ostream os(buf); + os << "Field access results in a dereference of a null pointer " + "(loaded from variable '" << VD->getName() << "')"; + Ranges.push_back(M->getBase()->getSourceRange()); + } + } + break; } default: break; @@ -117,19 +134,23 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, bugreporter::GetDerefExpr(N)); - + + for (llvm::SmallVectorImpl<SourceRange>::iterator + I = Ranges.begin(), E = Ranges.end(); I!=E; ++I) + report->addRange(*I); + C.EmitReport(report); return; } else { // Otherwise, we have the case where the location could either be // null or not-null. Record the error node as an "implicit" null - // dereference. + // dereference. if (ExplodedNode *N = C.GenerateSink(nullState)) ImplicitNullDerefNodes.push_back(N); } } - + // From this point forward, we know that the location is not null. C.addTransition(notNullState); } diff --git a/test/Analysis/inline.c b/test/Analysis/inline.c index 13d4f7fba4..952de737f7 100644 --- a/test/Analysis/inline.c +++ b/test/Analysis/inline.c @@ -15,6 +15,6 @@ void f2() { } if (x == 2) { int *p = 0; - *p = 3; // expected-warning{{Dereference of null pointer loaded from variable}} + *p = 3; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} } } diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 704ad339e1..5376ca0eb3 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -26,7 +26,7 @@ int f2(struct foo_struct* p) { if (p) p->x = 1; - return p->x++; // expected-warning{{Dereference of null pointer}} + return p->x++; // expected-warning{{Field access results in a dereference of a null pointer (loaded from variable 'p')}} } int f3(char* x) { @@ -57,7 +57,7 @@ int f4(int *p) { return 1; int *q = (int*) x; - return *q; // expected-warning{{Dereference of null pointer loaded from variable 'q'}} + return *q; // expected-warning{{Dereference of null pointer (loaded from variable 'q')}} } int f4_b() { diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m index f49fef5d6d..aa866de03c 100644 --- a/test/Analysis/plist-output.m +++ b/test/Analysis/plist-output.m @@ -124,7 +124,7 @@ void test_null_field(void) { // CHECK: <array> // CHECK: <dict> // CHECK: <key>line</key><integer>5</integer> -// CHECK: <key>col</key><integer>3</integer> +// CHECK: <key>col</key><integer>4</integer> // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: <dict> @@ -135,12 +135,12 @@ void test_null_field(void) { // CHECK: </array> // CHECK: </array> // CHECK: <key>extended_message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>category</key><string>Logic error</string> // CHECK: <key>type</key><string>Dereference of null pointer</string> // CHECK: <key>location</key> @@ -262,7 +262,7 @@ void test_null_field(void) { // CHECK: <array> // CHECK: <dict> // CHECK: <key>line</key><integer>11</integer> -// CHECK: <key>col</key><integer>3</integer> +// CHECK: <key>col</key><integer>4</integer> // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: <dict> @@ -273,12 +273,12 @@ void test_null_field(void) { // CHECK: </array> // CHECK: </array> // CHECK: <key>extended_message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>category</key><string>Logic error</string> // CHECK: <key>type</key><string>Dereference of null pointer</string> // CHECK: <key>location</key> @@ -400,7 +400,7 @@ void test_null_field(void) { // CHECK: <array> // CHECK: <dict> // CHECK: <key>line</key><integer>18</integer> -// CHECK: <key>col</key><integer>3</integer> +// CHECK: <key>col</key><integer>4</integer> // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: <dict> @@ -411,12 +411,12 @@ void test_null_field(void) { // CHECK: </array> // CHECK: </array> // CHECK: <key>extended_message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'q'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'q')</string> // CHECK: <key>message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'q'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'q')</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Dereference of null pointer loaded from variable 'q'</string> +// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'q')</string> // CHECK: <key>category</key><string>Logic error</string> // CHECK: <key>type</key><string>Dereference of null pointer</string> // CHECK: <key>location</key> @@ -538,7 +538,7 @@ void test_null_field(void) { // CHECK: <array> // CHECK: <dict> // CHECK: <key>line</key><integer>23</integer> -// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>col</key><integer>6</integer> // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: <dict> @@ -549,12 +549,12 @@ void test_null_field(void) { // CHECK: </array> // CHECK: </array> // CHECK: <key>extended_message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>category</key><string>Logic error</string> // CHECK: <key>type</key><string>Dereference of null pointer</string> // CHECK: <key>location</key> @@ -710,7 +710,7 @@ void test_null_field(void) { // CHECK: <array> // CHECK: <dict> // CHECK: <key>line</key><integer>30</integer> -// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>col</key><integer>6</integer> // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: <dict> @@ -721,12 +721,12 @@ void test_null_field(void) { // CHECK: </array> // CHECK: </array> // CHECK: <key>extended_message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>message</key> -// CHECK: <string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Dereference of null pointer loaded from variable 'p'</string> +// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string> // CHECK: <key>category</key><string>Logic error</string> // CHECK: <key>type</key><string>Dereference of null pointer</string> // CHECK: <key>location</key> |