[cfe-commits] r104584 - in /cfe/trunk: include/clang/Checker/PathSensitive/Store.h lib/Checker/CMakeLists.txt lib/Checker/CastSizeChecker.cpp lib/Checker/GRExprEngineExperimentalChecks.cpp lib/Checker/GRExprEngineInternalChecks.h lib/Checker/RegionStore.cpp test/Analysis/malloc.c
Zhongxing Xu
xuzhongxing at gmail.com
Mon May 24 21:59:20 PDT 2010
Author: zhongxingxu
Date: Mon May 24 23:59:19 2010
New Revision: 104584
URL: http://llvm.org/viewvc/llvm-project?rev=104584&view=rev
Log:
CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
whether the size of the symbolic region is a multiple of the size of T.
Fixes PR6123 and PR7217.
Added:
cfe/trunk/lib/Checker/CastSizeChecker.cpp
Modified:
cfe/trunk/include/clang/Checker/PathSensitive/Store.h
cfe/trunk/lib/Checker/CMakeLists.txt
cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h
cfe/trunk/lib/Checker/RegionStore.cpp
cfe/trunk/test/Analysis/malloc.c
Modified: cfe/trunk/include/clang/Checker/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/Store.h?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/Store.h Mon May 24 23:59:19 2010
@@ -18,6 +18,7 @@
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/Checker/PathSensitive/ValueManager.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
namespace clang {
@@ -167,10 +168,15 @@
// FIXME: Make out-of-line.
virtual const GRState *setExtent(const GRState *state,
- const MemRegion *region, SVal extent) {
+ const MemRegion *region, SVal extent) {
return state;
}
+ virtual llvm::Optional<SVal> getExtent(const GRState *state,
+ const MemRegion *R) {
+ return llvm::Optional<SVal>();
+ }
+
/// EnterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
virtual const GRState *EnterStackFrame(const GRState *state,
Modified: cfe/trunk/lib/Checker/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/CMakeLists.txt?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/CMakeLists.txt (original)
+++ cfe/trunk/lib/Checker/CMakeLists.txt Mon May 24 23:59:19 2010
@@ -14,6 +14,7 @@
BuiltinFunctionChecker.cpp
CallAndMessageChecker.cpp
CallInliner.cpp
+ CastSizeChecker.cpp
CastToStructChecker.cpp
CFRefCount.cpp
CheckDeadStores.cpp
@@ -70,4 +71,4 @@
VLASizeChecker.cpp
)
-add_dependencies(clangChecker ClangStmtNodes)
\ No newline at end of file
+add_dependencies(clangChecker ClangStmtNodes)
Added: cfe/trunk/lib/Checker/CastSizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/CastSizeChecker.cpp?rev=104584&view=auto
==============================================================================
--- cfe/trunk/lib/Checker/CastSizeChecker.cpp (added)
+++ cfe/trunk/lib/Checker/CastSizeChecker.cpp Mon May 24 23:59:19 2010
@@ -0,0 +1,82 @@
+//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
+// whether the size of the symbolic region is a multiple of the size of T.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/CharUnits.h"
+#include "clang/Checker/BugReporter/BugType.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
+ BuiltinBug *BT;
+public:
+ CastSizeChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+};
+}
+
+void *CastSizeChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+ ASTContext &Ctx = C.getASTContext();
+ QualType ToTy = Ctx.getCanonicalType(CE->getType());
+ PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+ if (!ToPTy)
+ return;
+
+ QualType ToPointeeTy = ToPTy->getPointeeType();
+
+ const MemRegion *R = C.getState()->getSVal(E).getAsRegion();
+ if (R == 0)
+ return;
+
+ const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+ if (SR == 0)
+ return;
+
+ llvm::Optional<SVal> V =
+ C.getEngine().getStoreManager().getExtent(C.getState(), SR);
+ if (!V)
+ return;
+
+ const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(V);
+ if (!CI)
+ return;
+
+ CharUnits RegionSize = CharUnits::fromQuantity(CI->getValue().getSExtValue());
+ CharUnits TypeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
+ if (RegionSize % TypeSize != 0) {
+ if (ExplodedNode *N = C.GenerateSink()) {
+ if (!BT)
+ BT = new BuiltinBug("Cast region with wrong size.",
+ "Cast a region whose size is not a multiple of the"
+ " destination type size.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(CE->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+
+void clang::RegisterCastSizeChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new CastSizeChecker());
+}
Modified: cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp Mon May 24 23:59:19 2010
@@ -36,5 +36,6 @@
RegisterPointerSubChecker(Eng);
RegisterPointerArithChecker(Eng);
RegisterCastToStructChecker(Eng);
+ RegisterCastSizeChecker(Eng);
RegisterArrayBoundChecker(Eng);
}
Modified: cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h Mon May 24 23:59:19 2010
@@ -26,6 +26,7 @@
void RegisterBuiltinFunctionChecker(GRExprEngine &Eng);
void RegisterCallAndMessageChecker(GRExprEngine &Eng);
void RegisterCastToStructChecker(GRExprEngine &Eng);
+void RegisterCastSizeChecker(GRExprEngine &Eng);
void RegisterDereferenceChecker(GRExprEngine &Eng);
void RegisterDivZeroChecker(GRExprEngine &Eng);
void RegisterFixedAddressChecker(GRExprEngine &Eng);
Modified: cfe/trunk/lib/Checker/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/RegionStore.cpp?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/RegionStore.cpp (original)
+++ cfe/trunk/lib/Checker/RegionStore.cpp Mon May 24 23:59:19 2010
@@ -364,7 +364,18 @@
// Region "extents".
//===------------------------------------------------------------------===//
- const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
+ const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent){
+ return state->set<RegionExtents>(R, Extent);
+ }
+
+ Optional<SVal> getExtent(const GRState *state, const MemRegion *R) {
+ const SVal *V = state->get<RegionExtents>(R);
+ if (V)
+ return *V;
+ else
+ return Optional<SVal>();
+ }
+
DefinedOrUnknownSVal getSizeInElements(const GRState *state,
const MemRegion* R, QualType EleTy);
@@ -798,12 +809,6 @@
return UnknownVal();
}
-const GRState *RegionStoreManager::setExtent(const GRState *state,
- const MemRegion *region,
- SVal extent) {
- return state->set<RegionExtents>(region, extent);
-}
-
//===----------------------------------------------------------------------===//
// Location and region casting.
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=104584&r1=104583&r2=104584&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Mon May 24 23:59:19 2010
@@ -6,16 +6,16 @@
void *calloc(size_t nmemb, size_t size);
void f1() {
- int *p = malloc(10);
+ int *p = malloc(12);
return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
}
void f1_b() {
- int *p = malloc(10); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+ int *p = malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
}
void f2() {
- int *p = malloc(10);
+ int *p = malloc(12);
free(p);
free(p); // expected-warning{{Try to free a memory block that has been released}}
}
@@ -25,7 +25,7 @@
// or inter-procedural analysis, this is a conservative answer.
int *f3() {
static int *p = 0;
- p = malloc(10);
+ p = malloc(12);
return p; // no-warning
}
@@ -34,18 +34,18 @@
// functions or inter-procedural analysis, this is a conservative answer.
static int *p_f4 = 0;
int *f4() {
- p_f4 = malloc(10);
+ p_f4 = malloc(12);
return p_f4; // no-warning
}
int *f5() {
- int *q = malloc(10);
+ int *q = malloc(12);
q = realloc(q, 20);
return q; // no-warning
}
void f6() {
- int *p = malloc(10);
+ int *p = malloc(12);
if (!p)
return; // no-warning
else
@@ -67,3 +67,13 @@
free(x);
x[0] = 'a'; // expected-warning{{Use dynamically allocated memory after it is freed.}}
}
+
+void PR6123() {
+ int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+}
+
+void PR7217() {
+ int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+ buf[1] = 'c'; // not crash
+
+}
More information about the cfe-commits
mailing list