CastToStructChecker.cpp revision 23c5497d36cbf0506f48575b6d89abb4dde1b5dc
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===// 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// The LLVM Compiler Infrastructure 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// This file is distributed under the University of Illinois Open Source 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// License. See LICENSE.TXT for details. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===// 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// This files defines CastToStructChecker, a builtin checker that checks for 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// cast from non-struct pointer to struct pointer. 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// This check corresponds to CWE-588. 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===// 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "ClangSACheckers.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/Checker.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comusing namespace clang; 23d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comusing namespace ento; 24d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnamespace { 26d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comclass CastToStructChecker : public Checker< check::PreStmt<CastExpr> > { 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable llvm::OwningPtr<BuiltinBug> BT; 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; 31d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com}; 32d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com} 33d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 34d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comvoid CastToStructChecker::checkPreStmt(const CastExpr *CE, 35d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com CheckerContext &C) const { 36d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com const Expr *E = CE->getSubExpr(); 37d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com ASTContext &Ctx = C.getASTContext(); 38d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com QualType OrigTy = Ctx.getCanonicalType(E->getType()); 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com QualType ToTy = Ctx.getCanonicalType(CE->getType()); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr()); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); 43d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 44d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (!ToPTy || !OrigPTy) 45d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return; 46d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 47d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com QualType OrigPointeeTy = OrigPTy->getPointeeType(); 48d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com QualType ToPointeeTy = ToPTy->getPointeeType(); 49d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 50d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (!ToPointeeTy->isStructureOrClassType()) 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // We allow cast from void*. 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (OrigPointeeTy->isVoidType()) 55d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return; 56d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 57d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // Now the cast-to-type is struct pointer, the original type is not void*. 58d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (!OrigPointeeTy->isRecordType()) { 59d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (ExplodedNode *N = C.addTransition()) { 60d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (!BT) 61d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com BT.reset(new BuiltinBug("Cast from non-struct type to struct type", 62d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com "Casting a non-structure type to a structure type " 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "and accessing a field can lead to memory access " 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "errors or data corruption.")); 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport *R = new BugReport(*BT,BT->getDescription(), N); 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com R->addRange(CE->getSourceRange()); 67d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com C.EmitReport(R); 68d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 69d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 70d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com} 71d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 72d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comvoid ento::registerCastToStructChecker(CheckerManager &mgr) { 73d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com mgr.registerChecker<CastToStructChecker>(); 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com