14f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
24f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//
34f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//                     The LLVM Compiler Infrastructure
44f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//
54f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu// This file is distributed under the University of Illinois Open Source
64f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu// License. See LICENSE.TXT for details.
74f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//
84f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//===----------------------------------------------------------------------===//
94f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//
104f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu// This files defines CastToStructChecker, a builtin checker that checks for
11368979179c2ae4f1ff22786fc5c83c20f1cbc042Zhongxing Xu// cast from non-struct pointer to struct pointer.
124f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu// This check corresponds to CWE-588.
134f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//
144f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu//===----------------------------------------------------------------------===//
154f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
1623ade507cecd24b03f5e4b5ebaea48eb38060262Argyrios Kyrtzidis#include "ClangSACheckers.h"
17ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
18695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
214f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
224f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xuusing namespace clang;
239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
244f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
254f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xunamespace {
26ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CastToStructChecker : public Checker< check::PreStmt<CastExpr> > {
276f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<BuiltinBug> BT;
28983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis
294f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xupublic:
30983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
314f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu};
324f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu}
334f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
34983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidisvoid CastToStructChecker::checkPreStmt(const CastExpr *CE,
35983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis                                       CheckerContext &C) const {
364f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  const Expr *E = CE->getSubExpr();
374f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  ASTContext &Ctx = C.getASTContext();
384f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  QualType OrigTy = Ctx.getCanonicalType(E->getType());
394f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  QualType ToTy = Ctx.getCanonicalType(CE->getType());
404f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
41f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall  const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
42f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall  const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
434f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
444f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  if (!ToPTy || !OrigPTy)
454f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu    return;
464f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
474f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  QualType OrigPointeeTy = OrigPTy->getPointeeType();
484f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  QualType ToPointeeTy = ToPTy->getPointeeType();
494f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
50fb87b89fc9eb103e19fb8e4b925c23f0bd091b99Douglas Gregor  if (!ToPointeeTy->isStructureOrClassType())
514f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu    return;
524f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
534f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  // We allow cast from void*.
544f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  if (OrigPointeeTy->isVoidType())
554f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu    return;
564f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
574f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  // Now the cast-to-type is struct pointer, the original type is not void*.
584f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  if (!OrigPointeeTy->isRecordType()) {
590bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks    if (ExplodedNode *N = C.addTransition()) {
604f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu      if (!BT)
61983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis        BT.reset(new BuiltinBug("Cast from non-struct type to struct type",
624f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu                            "Casting a non-structure type to a structure type "
634f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu                            "and accessing a field can lead to memory access "
64983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis                            "errors or data corruption."));
65e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      BugReport *R = new BugReport(*BT,BT->getDescription(), N);
664f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu      R->addRange(CE->getSourceRange());
674f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu      C.EmitReport(R);
684f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu    }
694f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu  }
704f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu}
714f3dc698a1bbeea16155e51dfc7d0f69ff689598Zhongxing Xu
72695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCastToStructChecker(CheckerManager &mgr) {
73983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  mgr.registerChecker<CastToStructChecker>();
74695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis}
75