CastToStructChecker.cpp revision 23ade507cecd24b03f5e4b5ebaea48eb38060262
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/PathSensitive/CheckerVisitor.h" 19 20using namespace clang; 21using namespace ento; 22 23namespace { 24class CastToStructChecker 25 : public CheckerVisitor<CastToStructChecker> { 26 BuiltinBug *BT; 27public: 28 CastToStructChecker() : BT(0) {} 29 static void *getTag(); 30 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B); 31}; 32} 33 34void *CastToStructChecker::getTag() { 35 static int x; 36 return &x; 37} 38 39void 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 const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr()); 47 const 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 77void ento::registerCastToStructChecker(ExprEngine &Eng) { 78 Eng.registerCheck(new CastToStructChecker()); 79} 80