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