[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