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 "clang/StaticAnalyzer/BugReporter/BugType.h" 17 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h" 18 #include "ExprEngineInternalChecks.h" 19 20 using namespace clang; 21 using namespace ento; 22 23 namespace { 24 class CastToStructChecker 25 : public CheckerVisitor<CastToStructChecker> { 26 BuiltinBug *BT; 27 public: 28 CastToStructChecker() : BT(0) {} 29 static void *getTag(); 30 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B); 31 }; 32 } 33 34 void *CastToStructChecker::getTag() { 35 static int x; 36 return &x; 37 } 38 39 void CastToStructChecker::PreVisitCastExpr(CheckerContext &C, 40 const CastExpr *CE) { 41 const Expr *E = CE->getSubExpr(); 42 ASTContext &Ctx = C.getASTContext(); 43 QualType OrigTy = Ctx.getCanonicalType(E->getType()); 44 QualType ToTy = Ctx.getCanonicalType(CE->getType()); 45 46 PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr()); 47 PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); 48 49 if (!ToPTy || !OrigPTy) 50 return; 51 52 QualType OrigPointeeTy = OrigPTy->getPointeeType(); 53 QualType ToPointeeTy = ToPTy->getPointeeType(); 54 55 if (!ToPointeeTy->isStructureOrClassType()) 56 return; 57 58 // We allow cast from void*. 59 if (OrigPointeeTy->isVoidType()) 60 return; 61 62 // Now the cast-to-type is struct pointer, the original type is not void*. 63 if (!OrigPointeeTy->isRecordType()) { 64 if (ExplodedNode *N = C.generateNode()) { 65 if (!BT) 66 BT = new BuiltinBug("Cast from non-struct type to struct type", 67 "Casting a non-structure type to a structure type " 68 "and accessing a field can lead to memory access " 69 "errors or data corruption."); 70 RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N); 71 R->addRange(CE->getSourceRange()); 72 C.EmitReport(R); 73 } 74 } 75 } 76 77 void ento::RegisterCastToStructChecker(ExprEngine &Eng) { 78 Eng.registerCheck(new CastToStructChecker()); 79 } 80