[cfe-commits] r86529 - in /cfe/trunk: include/clang/Analysis/PathSensitive/CheckerVisitor.def include/clang/Analysis/PathSensitive/CheckerVisitor.h lib/Analysis/CastToStructChecker.cpp lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/GRExprEngineInternalChecks.h test/Analysis/array-struct.c test/Analysis/misc-ps-region-store.m
Zhongxing Xu
xuzhongxing at gmail.com
Mon Nov 9 00:07:38 PST 2009
Author: zhongxingxu
Date: Mon Nov 9 02:07:38 2009
New Revision: 86529
URL: http://llvm.org/viewvc/llvm-project?rev=86529&view=rev
Log:
Add checker for CWE-588: Attempt to Access Child of a Non-structure Pointer.
Added:
cfe/trunk/lib/Analysis/CastToStructChecker.cpp
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def
cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.h
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
cfe/trunk/test/Analysis/array-struct.c
cfe/trunk/test/Analysis/misc-ps-region-store.m
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def Mon Nov 9 02:07:38 2009
@@ -13,6 +13,7 @@
PREVISIT(BinaryOperator)
PREVISIT(CallExpr)
+PREVISIT(CastExpr)
PREVISIT(DeclStmt)
PREVISIT(ObjCMessageExpr)
PREVISIT(ReturnStmt)
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.h?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.h Mon Nov 9 02:07:38 2009
@@ -36,10 +36,19 @@
default:
assert(false && "Unsupport statement.");
return;
+
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ExplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ static_cast<ImplClass*>(this)->PreVisitCastExpr(C,
+ static_cast<const CastExpr*>(S));
+ break;
+
case Stmt::CompoundAssignOperatorClass:
static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C,
static_cast<const BinaryOperator*>(S));
break;
+
#define PREVISIT(NAME) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
Added: cfe/trunk/lib/Analysis/CastToStructChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CastToStructChecker.cpp?rev=86529&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/CastToStructChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/CastToStructChecker.cpp Mon Nov 9 02:07:38 2009
@@ -0,0 +1,78 @@
+//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines CastToStructChecker, a builtin checker that checks for
+// assignment of a fixed address to a pointer.
+// This check corresponds to CWE-588.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN CastToStructChecker
+ : public CheckerVisitor<CastToStructChecker> {
+ BuiltinBug *BT;
+public:
+ CastToStructChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+};
+}
+
+void *CastToStructChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
+ const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+ ASTContext &Ctx = C.getASTContext();
+ QualType OrigTy = Ctx.getCanonicalType(E->getType());
+ QualType ToTy = Ctx.getCanonicalType(CE->getType());
+
+ PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
+ PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+ if (!ToPTy || !OrigPTy)
+ return;
+
+ QualType OrigPointeeTy = OrigPTy->getPointeeType();
+ QualType ToPointeeTy = ToPTy->getPointeeType();
+
+ if (!ToPointeeTy->isRecordType())
+ return;
+
+ // We allow cast from void*.
+ if (OrigPointeeTy->isVoidType())
+ return;
+
+ // Now the cast-to-type is struct pointer, the original type is not void*.
+ if (!OrigPointeeTy->isRecordType()) {
+ if (ExplodedNode *N = C.GenerateNode(CE)) {
+ if (!BT)
+ BT = new BuiltinBug("Cast from non-struct type to struct type",
+ "Casting a non-structure type to a structure type "
+ "and accessing a field can lead to memory access "
+ "errors or data corruption.");
+ RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription().c_str(),
+ N);
+ R->addRange(CE->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+void clang::RegisterCastToStructChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new CastToStructChecker());
+}
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Nov 9 02:07:38 2009
@@ -2035,7 +2035,8 @@
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst){
+void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst){
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@@ -2048,16 +2049,18 @@
else
Visit(Ex, Pred, S1);
+ ExplodedNodeSet S2;
+ CheckerVisit(CastE, S2, S1, true);
+
// Check for casting to "void".
if (T->isVoidType()) {
- for (ExplodedNodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1)
- Dst.Add(*I1);
-
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
+ Dst.Add(*I);
return;
}
- for (ExplodedNodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
- ExplodedNode* N = *I1;
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ExplodedNode* N = *I;
const GRState* state = GetState(N);
SVal V = state->getSVal(Ex);
const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Mon Nov 9 02:07:38 2009
@@ -416,4 +416,6 @@
RegisterFixedAddressChecker(*this);
// Note that this must be registered after ReturnStackAddressChecker.
RegisterReturnPointerRangeChecker(*this);
+
+ RegisterCastToStructChecker(*this);
}
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Mon Nov 9 02:07:38 2009
@@ -26,5 +26,6 @@
void RegisterVLASizeChecker(GRExprEngine &Eng);
void RegisterPointerSubChecker(GRExprEngine &Eng);
void RegisterFixedAddressChecker(GRExprEngine &Eng);
+void RegisterCastToStructChecker(GRExprEngine &Eng);
} // end clang namespace
#endif
Modified: cfe/trunk/test/Analysis/array-struct.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct.c?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/array-struct.c (original)
+++ cfe/trunk/test/Analysis/array-struct.c Mon Nov 9 02:07:38 2009
@@ -153,7 +153,7 @@
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'.
void f16(struct s3 *p) {
- struct s3 a = *((struct s3*) ((char*) &p[0]));
+ struct s3 a = *((struct s3*) ((char*) &p[0])); // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
}
void inv(struct s1 *);
Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=86529&r1=86528&r2=86529&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Mon Nov 9 02:07:38 2009
@@ -286,7 +286,7 @@
int test_handle_array_wrapper() {
struct ArrayWrapper x;
test_handle_array_wrapper(&x);
- struct WrappedStruct *p = (struct WrappedStruct*) x.y;
+ struct WrappedStruct *p = (struct WrappedStruct*) x.y; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
return p->z; // no-warning
}
More information about the cfe-commits
mailing list