From bc3a021df7f9ee4c4d1e9ec3c2aac2ef6d883206 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 30 Oct 2009 17:24:47 +0000 Subject: [PATCH] Move all logic for the null dereference checker from GRExprEngineInternalChecks.cpp to a separate .cpp file. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85595 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/NullDerefChecker.h | 26 ++----- lib/Analysis/CMakeLists.txt | 1 + lib/Analysis/GRExprEngineInternalChecks.cpp | 47 +----------- lib/Analysis/NullDerefChecker.cpp | 76 +++++++++++++++++++ 4 files changed, 86 insertions(+), 64 deletions(-) create mode 100644 lib/Analysis/NullDerefChecker.cpp diff --git a/include/clang/Analysis/PathSensitive/NullDerefChecker.h b/include/clang/Analysis/PathSensitive/NullDerefChecker.h index 05c4b360f8..6905d6834b 100644 --- a/include/clang/Analysis/PathSensitive/NullDerefChecker.h +++ b/include/clang/Analysis/PathSensitive/NullDerefChecker.h @@ -1,4 +1,4 @@ -//== NullDerefChecker - Null dereference checker ----------------*- C++ -*--==// +//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==// // // The LLVM Compiler Infrastructure // @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This defines NullDerefChecker, a builtin check in GRExprEngine that performs +// checks for null pointers at loads and stores. +// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_NULLDEREFCHECKER #define LLVM_CLANG_NULLDEREFCHECKER @@ -17,31 +22,16 @@ namespace clang { class ExplodedNode; -class NullDeref : public BuiltinBug { -public: - NullDeref() - : BuiltinBug(0, "Null dereference", "Dereference of null pointer") {} - - void registerInitialVisitors(BugReporterContext& BRC, - const ExplodedNode* N, - BuiltinBugReport *R); -}; - class NullDerefChecker : public Checker { - NullDeref *BT; + BuiltinBug *BT; llvm::SmallVector ImplicitNullDerefNodes; public: - NullDerefChecker() : BT(0) {} ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, const GRState *state, SVal V,GRExprEngine &Eng); - static void *getTag() { - static int x = 0; - return &x; - } - + static void *getTag(); typedef llvm::SmallVectorImpl::iterator iterator; iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); } iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); } diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 89c1783cc2..d3bf42ba60 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -28,6 +28,7 @@ add_clang_library(clangAnalysis GRState.cpp LiveVariables.cpp MemRegion.cpp + NullDerefChecker.cpp PathDiagnostic.cpp RangeConstraintManager.cpp RegionStore.cpp diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 526bc93e85..81b465e532 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -66,11 +66,6 @@ void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) { for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(), GetNode(I))); } -void NullDeref::registerInitialVisitors(BugReporterContext& BRC, - const ExplodedNode* N, - BuiltinBugReport *R) { - registerTrackNullOrUndefValue(BRC, bugreporter::GetDerefExpr(N), N); -} class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug { public: @@ -794,48 +789,8 @@ ExplodedNode *CheckUndefDeref::CheckLocation(const Stmt *S, ExplodedNode *Pred, return Pred; } -ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, - GRExprEngine &Eng) { - Loc *LV = dyn_cast(&V); - - // If the value is not a location, don't touch the node. - if (!LV) - return Pred; - - const GRState *NotNullState = state->Assume(*LV, true); - const GRState *NullState = state->Assume(*LV, false); - - GRStmtNodeBuilder &Builder = Eng.getBuilder(); - BugReporter &BR = Eng.getBugReporter(); - - // The explicit NULL case. - if (NullState) { - // Use the GDM to mark in the state what lval was null. - const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV); - NullState = NullState->set(PersistentLV); - - ExplodedNode *N = Builder.generateNode(S, NullState, Pred, - ProgramPoint::PostNullCheckFailedKind); - if (N) { - N->markAsSink(); - - if (!NotNullState) { // Explicit null case. - if (!BT) - BT = new NullDeref(); - BR.EmitReport(new BuiltinBugReport(*BT,BT->getDescription().c_str(),N)); - return 0; - } else // Implicit null case. - ImplicitNullDerefNodes.push_back(N); - } - } - - if (!NotNullState) - return 0; - return Builder.generateNode(S, NotNullState, Pred, - ProgramPoint::PostLocationChecksSucceedKind); -} } // end clang namespace + //===----------------------------------------------------------------------===// // Check registration. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/NullDerefChecker.cpp b/lib/Analysis/NullDerefChecker.cpp new file mode 100644 index 0000000000..2a899d2b06 --- /dev/null +++ b/lib/Analysis/NullDerefChecker.cpp @@ -0,0 +1,76 @@ +//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines NullDerefChecker, a builtin check in GRExprEngine that performs +// checks for null pointers at loads and stores. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/NullDerefChecker.h" +#include "clang/Analysis/PathSensitive/GRExprEngine.h" +#include "clang/Analysis/PathSensitive/BugReporter.h" + +using namespace clang; + +void *NullDerefChecker::getTag() { + static int x = 0; + return &x; +} + +ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred, + const GRState *state, SVal V, + GRExprEngine &Eng) { + Loc *LV = dyn_cast(&V); + + // If the value is not a location, don't touch the node. + if (!LV) + return Pred; + + const GRState *NotNullState = state->Assume(*LV, true); + const GRState *NullState = state->Assume(*LV, false); + + GRStmtNodeBuilder &Builder = Eng.getBuilder(); + BugReporter &BR = Eng.getBugReporter(); + + // The explicit NULL case. + if (NullState) { + // Use the GDM to mark in the state what lval was null. + const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV); + NullState = NullState->set(PersistentLV); + + ExplodedNode *N = Builder.generateNode(S, NullState, Pred, + ProgramPoint::PostNullCheckFailedKind); + if (N) { + N->markAsSink(); + + if (!NotNullState) { // Explicit null case. + if (!BT) + BT = new BuiltinBug(NULL, "Null dereference", + "Dereference of null pointer"); + + EnhancedBugReport *R = + new EnhancedBugReport(*BT, BT->getDescription().c_str(), N); + + R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + bugreporter::GetDerefExpr(N)); + + BR.EmitReport(R); + + return 0; + } else // Implicit null case. + ImplicitNullDerefNodes.push_back(N); + } + } + + if (!NotNullState) + return 0; + + return Builder.generateNode(S, NotNullState, Pred, + ProgramPoint::PostLocationChecksSucceedKind); +} -- 2.40.0