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