IsParam = true;
}
}
+
+ // If this is a CXXTempObjectRegion, the Expr responsible for its creation
+ // is wrapped inside of it.
+ if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R))
+ InitE = TmpR->getExpr();
}
if (!StoreSite)
return 0;
}
+static const MemRegion *getLocationRegionIfReference(const Expr *E,
+ const ExplodedNode *N) {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (!VD->getType()->isReferenceType())
+ return 0;
+ ProgramStateManager &StateMgr = N->getState()->getStateManager();
+ MemRegionManager &MRMgr = StateMgr.getRegionManager();
+ return MRMgr.getVarRegion(VD, N->getLocationContext());
+ }
+ }
+
+ // FIXME: This does not handle other kinds of null references,
+ // for example, references from FieldRegions:
+ // struct Wrapper { int &ref; };
+ // Wrapper w = { *(int *)0 };
+ // w.ref = 1;
+
+ return 0;
+}
+
bool bugreporter::trackNullOrUndefValue(const ExplodedNode *ErrorNode,
const Stmt *S,
BugReport &report, bool IsArg) {
if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
const MemRegion *R = 0;
- // First check if this is a DeclRefExpr for a C++ reference type.
- // For those, we want the location of the reference.
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Inner)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- if (VD->getType()->isReferenceType()) {
- ProgramStateManager &StateMgr = state->getStateManager();
- MemRegionManager &MRMgr = StateMgr.getRegionManager();
- R = MRMgr.getVarRegion(VD, N->getLocationContext());
- }
+ // Find the ExplodedNode where the lvalue (the value of 'Ex')
+ // was computed. We need this for getting the location value.
+ const ExplodedNode *LVNode = N;
+ while (LVNode) {
+ if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
+ if (P->getStmt() == Inner)
+ break;
}
+ LVNode = LVNode->getFirstPred();
}
+ assert(LVNode && "Unable to find the lvalue node.");
+ ProgramStateRef LVState = LVNode->getState();
+ SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
+
+ if (LVState->isNull(LVal).isConstrainedTrue()) {
+ // In case of C++ references, we want to differentiate between a null
+ // reference and reference to null pointer.
+ // If the LVal is null, check if we are dealing with null reference.
+ // For those, we want to track the location of the reference.
+ if (const MemRegion *RR = getLocationRegionIfReference(Inner, N))
+ R = RR;
+ } else {
+ R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
- // For all other cases, find the location by scouring the ExplodedGraph.
- if (!R) {
- // Find the ExplodedNode where the lvalue (the value of 'Ex')
- // was computed. We need this for getting the location value.
- const ExplodedNode *LVNode = N;
- while (LVNode) {
- if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) {
- if (P->getStmt() == Inner)
- break;
- }
- LVNode = LVNode->getFirstPred();
+ // If this is a C++ reference to a null pointer, we are tracking the
+ // pointer. In additon, we should find the store at which the reference
+ // got initialized.
+ if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) {
+ if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>())
+ report.addVisitor(new FindLastStoreBRVisitor(*KV, RR));
}
- assert(LVNode && "Unable to find the lvalue node.");
- ProgramStateRef LVState = LVNode->getState();
- R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion();
}
if (R) {
extern void use(int &ref);
use(ref); // expected-warning{{Forming reference to null pointer}}
// expected-note@-1{{Forming reference to null pointer}}
+}
+
+int testRefToNullPtr() {
+ int *p = 0; // expected-note {{'p' initialized to a null pointer value}}
+ int *const &p2 = p; // expected-note{{'p2' initialized here}}
+ int *p3 = p2; // expected-note {{'p3' initialized to a null pointer value}}
+ return *p3; // expected-warning {{Dereference of null pointer}}
+ // expected-note@-1{{Dereference of null pointer}}
+}
+
+int testRefToNullPtr2() {
+ int *p = 0; // expected-note {{'p' initialized to a null pointer value}}
+ int *const &p2 = p;// expected-note{{'p2' initialized here}}
+ return *p2; //expected-warning {{Dereference of null pointer}}
+ // expected-note@-1{{Dereference of null pointer}}
}
\ No newline at end of file