diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Checker/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/Checker/CastSizeChecker.cpp | 82 | ||||
-rw-r--r-- | lib/Checker/GRExprEngineExperimentalChecks.cpp | 1 | ||||
-rw-r--r-- | lib/Checker/GRExprEngineInternalChecks.h | 1 | ||||
-rw-r--r-- | lib/Checker/RegionStore.cpp | 19 |
5 files changed, 98 insertions, 8 deletions
diff --git a/lib/Checker/CMakeLists.txt b/lib/Checker/CMakeLists.txt index ce5a7361b9..9c6adc6bf2 100644 --- a/lib/Checker/CMakeLists.txt +++ b/lib/Checker/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_library(clangChecker BuiltinFunctionChecker.cpp CallAndMessageChecker.cpp CallInliner.cpp + CastSizeChecker.cpp CastToStructChecker.cpp CFRefCount.cpp CheckDeadStores.cpp @@ -70,4 +71,4 @@ add_clang_library(clangChecker VLASizeChecker.cpp ) -add_dependencies(clangChecker ClangStmtNodes)
\ No newline at end of file +add_dependencies(clangChecker ClangStmtNodes) diff --git a/lib/Checker/CastSizeChecker.cpp b/lib/Checker/CastSizeChecker.cpp new file mode 100644 index 0000000000..754d775a65 --- /dev/null +++ b/lib/Checker/CastSizeChecker.cpp @@ -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()); +} diff --git a/lib/Checker/GRExprEngineExperimentalChecks.cpp b/lib/Checker/GRExprEngineExperimentalChecks.cpp index 89b4e4b639..6066a1c74d 100644 --- a/lib/Checker/GRExprEngineExperimentalChecks.cpp +++ b/lib/Checker/GRExprEngineExperimentalChecks.cpp @@ -36,5 +36,6 @@ void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) { RegisterPointerSubChecker(Eng); RegisterPointerArithChecker(Eng); RegisterCastToStructChecker(Eng); + RegisterCastSizeChecker(Eng); RegisterArrayBoundChecker(Eng); } diff --git a/lib/Checker/GRExprEngineInternalChecks.h b/lib/Checker/GRExprEngineInternalChecks.h index d1176001ca..335b85e308 100644 --- a/lib/Checker/GRExprEngineInternalChecks.h +++ b/lib/Checker/GRExprEngineInternalChecks.h @@ -26,6 +26,7 @@ void RegisterAttrNonNullChecker(GRExprEngine &Eng); 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); diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 1e15d43a5a..0e4c4439f3 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -364,7 +364,18 @@ public: // Part of public interface to class. // 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 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, return UnknownVal(); } -const GRState *RegionStoreManager::setExtent(const GRState *state, - const MemRegion *region, - SVal extent) { - return state->set<RegionExtents>(region, extent); -} - //===----------------------------------------------------------------------===// // Location and region casting. //===----------------------------------------------------------------------===// |