1f4a2713aSLionel Sambuc //=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc // 10f4a2713aSLionel Sambuc // This files defines CastToStructChecker, a builtin checker that checks for 11f4a2713aSLionel Sambuc // cast from non-struct pointer to struct pointer. 12f4a2713aSLionel Sambuc // This check corresponds to CWE-588. 13f4a2713aSLionel Sambuc // 14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 15f4a2713aSLionel Sambuc 16f4a2713aSLionel Sambuc #include "ClangSACheckers.h" 17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h" 19f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h" 20f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21f4a2713aSLionel Sambuc 22f4a2713aSLionel Sambuc using namespace clang; 23f4a2713aSLionel Sambuc using namespace ento; 24f4a2713aSLionel Sambuc 25f4a2713aSLionel Sambuc namespace { 26f4a2713aSLionel Sambuc class CastToStructChecker : public Checker< check::PreStmt<CastExpr> > { 27*0a6a1f1dSLionel Sambuc mutable std::unique_ptr<BuiltinBug> BT; 28f4a2713aSLionel Sambuc 29f4a2713aSLionel Sambuc public: 30f4a2713aSLionel Sambuc void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; 31f4a2713aSLionel Sambuc }; 32f4a2713aSLionel Sambuc } 33f4a2713aSLionel Sambuc checkPreStmt(const CastExpr * CE,CheckerContext & C) const34f4a2713aSLionel Sambucvoid CastToStructChecker::checkPreStmt(const CastExpr *CE, 35f4a2713aSLionel Sambuc CheckerContext &C) const { 36f4a2713aSLionel Sambuc const Expr *E = CE->getSubExpr(); 37f4a2713aSLionel Sambuc ASTContext &Ctx = C.getASTContext(); 38f4a2713aSLionel Sambuc QualType OrigTy = Ctx.getCanonicalType(E->getType()); 39f4a2713aSLionel Sambuc QualType ToTy = Ctx.getCanonicalType(CE->getType()); 40f4a2713aSLionel Sambuc 41f4a2713aSLionel Sambuc const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr()); 42f4a2713aSLionel Sambuc const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); 43f4a2713aSLionel Sambuc 44f4a2713aSLionel Sambuc if (!ToPTy || !OrigPTy) 45f4a2713aSLionel Sambuc return; 46f4a2713aSLionel Sambuc 47f4a2713aSLionel Sambuc QualType OrigPointeeTy = OrigPTy->getPointeeType(); 48f4a2713aSLionel Sambuc QualType ToPointeeTy = ToPTy->getPointeeType(); 49f4a2713aSLionel Sambuc 50f4a2713aSLionel Sambuc if (!ToPointeeTy->isStructureOrClassType()) 51f4a2713aSLionel Sambuc return; 52f4a2713aSLionel Sambuc 53f4a2713aSLionel Sambuc // We allow cast from void*. 54f4a2713aSLionel Sambuc if (OrigPointeeTy->isVoidType()) 55f4a2713aSLionel Sambuc return; 56f4a2713aSLionel Sambuc 57f4a2713aSLionel Sambuc // Now the cast-to-type is struct pointer, the original type is not void*. 58f4a2713aSLionel Sambuc if (!OrigPointeeTy->isRecordType()) { 59f4a2713aSLionel Sambuc if (ExplodedNode *N = C.addTransition()) { 60f4a2713aSLionel Sambuc if (!BT) 61*0a6a1f1dSLionel Sambuc BT.reset( 62*0a6a1f1dSLionel Sambuc new BuiltinBug(this, "Cast from non-struct type to struct type", 63f4a2713aSLionel Sambuc "Casting a non-structure type to a structure type " 64f4a2713aSLionel Sambuc "and accessing a field can lead to memory access " 65f4a2713aSLionel Sambuc "errors or data corruption.")); 66f4a2713aSLionel Sambuc BugReport *R = new BugReport(*BT,BT->getDescription(), N); 67f4a2713aSLionel Sambuc R->addRange(CE->getSourceRange()); 68f4a2713aSLionel Sambuc C.emitReport(R); 69f4a2713aSLionel Sambuc } 70f4a2713aSLionel Sambuc } 71f4a2713aSLionel Sambuc } 72f4a2713aSLionel Sambuc registerCastToStructChecker(CheckerManager & mgr)73f4a2713aSLionel Sambucvoid ento::registerCastToStructChecker(CheckerManager &mgr) { 74f4a2713aSLionel Sambuc mgr.registerChecker<CastToStructChecker>(); 75f4a2713aSLionel Sambuc } 76