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 22using namespace clang; 23using namespace ento; 24 25namespace { 26class CastToStructChecker : public Checker< check::PreStmt<CastExpr> > { 27 mutable std::unique_ptr<BuiltinBug> BT; 28 29public: 30 void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; 31}; 32} 33 34void 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.addTransition()) { 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 BugReport *R = new BugReport(*BT,BT->getDescription(), N); 67 R->addRange(CE->getSourceRange()); 68 C.emitReport(R); 69 } 70 } 71} 72 73void ento::registerCastToStructChecker(CheckerManager &mgr) { 74 mgr.registerChecker<CastToStructChecker>(); 75} 76