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