summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Analysis/PathSensitive/GRExprEngine.h5
-rw-r--r--clang/lib/Analysis/GRExprEngine.cpp44
-rw-r--r--clang/test/Analysis/null-deref-ps.c21
3 files changed, 59 insertions, 11 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
index f7f228cfcca..e62a75b8737 100644
--- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -542,6 +542,11 @@ protected:
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
+ /// handles pointer to integer casts and array to integer casts.
+ void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
+ Expr* CastE, NodeTy* Pred, NodeSet& Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp
index 1487ed6f2ca..73df09a6f4a 100644
--- a/clang/lib/Analysis/GRExprEngine.cpp
+++ b/clang/lib/Analysis/GRExprEngine.cpp
@@ -1668,6 +1668,22 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
+void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
+ QualType PtrTy,
+ Expr* CastE, NodeTy* Pred,
+ NodeSet& Dst) {
+ if (!V.isUnknownOrUndef()) {
+ // FIXME: Determine if the number of bits of the target type is
+ // equal or exceeds the number of bits to store the pointer value.
+ // If not, flag an error.
+ unsigned bits = getContext().getTypeSize(PtrTy);
+ V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
+ }
+
+ MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V));
+}
+
+
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
NodeSet S1;
QualType T = CastE->getType();
@@ -1724,14 +1740,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
// Check for casts from pointers to integers.
if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
- unsigned bits = getContext().getTypeSize(ExTy);
-
- // FIXME: Determine if the number of bits of the target type is
- // equal or exceeds the number of bits to store the pointer value.
- // If not, flag an error.
-
- V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
- MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+ VisitCastPointerToInteger(V, St, ExTy, CastE, N, Dst);
continue;
}
@@ -1744,11 +1753,24 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
continue;
}
- // Check for casts from array type to pointer type.
+ // Check for casts from array type to another type.
if (ExTy->isArrayType()) {
- assert(T->isPointerType());
+ // We will always decay to a pointer.
V = StateMgr.ArrayToPointer(V);
- MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+
+ // Are we casting from an array to a pointer? If so just pass on
+ // the decayed value.
+ if (T->isPointerType()) {
+ MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+ continue;
+ }
+
+ // Are we casting from an array to an integer? If so, cast the decayed
+ // pointer value to an integer.
+ assert(T->isIntegerType());
+ QualType ElemTy = cast<ArrayType>(ExTy)->getElementType();
+ QualType PointerTy = getContext().getPointerType(ElemTy);
+ VisitCastPointerToInteger(V, St, PointerTy, CastE, N, Dst);
continue;
}
diff --git a/clang/test/Analysis/null-deref-ps.c b/clang/test/Analysis/null-deref-ps.c
index 028eaabc492..e0dddc8a59b 100644
--- a/clang/test/Analysis/null-deref-ps.c
+++ b/clang/test/Analysis/null-deref-ps.c
@@ -52,6 +52,27 @@ int f4(int *p) {
return *q; // expected-warning{{Dereference of null pointer.}}
}
+int f4_b() {
+ short array[2];
+ uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion initializing}}
+ short *p = x; // expected-warning{{incompatible integer to pointer conversion initializing}}
+
+ // The following branch should be infeasible.
+ if (!(p = &array[0])) {
+ p = 0;
+ *p = 1; // no-warning
+ }
+
+ if (p) {
+ *p = 5; // no-warning
+ p = 0;
+ }
+ else return;
+
+ *p += 10; // expected-warning{{Dereference of null pointer}}
+}
+
+
int f5() {
char *s = "hello world";
OpenPOWER on IntegriCloud