xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This files defines CastToStructChecker, a builtin checker that checks for
11f4a2713aSLionel Sambuc // cast from non-struct pointer to struct pointer.
12f4a2713aSLionel Sambuc // This check corresponds to CWE-588.
13f4a2713aSLionel Sambuc //
14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc #include "ClangSACheckers.h"
17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h"
19f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h"
20f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc using namespace clang;
23f4a2713aSLionel Sambuc using namespace ento;
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc namespace {
26f4a2713aSLionel Sambuc class CastToStructChecker : public Checker< check::PreStmt<CastExpr> > {
27*0a6a1f1dSLionel Sambuc   mutable std::unique_ptr<BuiltinBug> BT;
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc public:
30f4a2713aSLionel Sambuc   void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
31f4a2713aSLionel Sambuc };
32f4a2713aSLionel Sambuc }
33f4a2713aSLionel Sambuc 
checkPreStmt(const CastExpr * CE,CheckerContext & C) const34f4a2713aSLionel Sambuc void CastToStructChecker::checkPreStmt(const CastExpr *CE,
35f4a2713aSLionel Sambuc                                        CheckerContext &C) const {
36f4a2713aSLionel Sambuc   const Expr *E = CE->getSubExpr();
37f4a2713aSLionel Sambuc   ASTContext &Ctx = C.getASTContext();
38f4a2713aSLionel Sambuc   QualType OrigTy = Ctx.getCanonicalType(E->getType());
39f4a2713aSLionel Sambuc   QualType ToTy = Ctx.getCanonicalType(CE->getType());
40f4a2713aSLionel Sambuc 
41f4a2713aSLionel Sambuc   const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
42f4a2713aSLionel Sambuc   const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc   if (!ToPTy || !OrigPTy)
45f4a2713aSLionel Sambuc     return;
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc   QualType OrigPointeeTy = OrigPTy->getPointeeType();
48f4a2713aSLionel Sambuc   QualType ToPointeeTy = ToPTy->getPointeeType();
49f4a2713aSLionel Sambuc 
50f4a2713aSLionel Sambuc   if (!ToPointeeTy->isStructureOrClassType())
51f4a2713aSLionel Sambuc     return;
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc   // We allow cast from void*.
54f4a2713aSLionel Sambuc   if (OrigPointeeTy->isVoidType())
55f4a2713aSLionel Sambuc     return;
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc   // Now the cast-to-type is struct pointer, the original type is not void*.
58f4a2713aSLionel Sambuc   if (!OrigPointeeTy->isRecordType()) {
59f4a2713aSLionel Sambuc     if (ExplodedNode *N = C.addTransition()) {
60f4a2713aSLionel Sambuc       if (!BT)
61*0a6a1f1dSLionel Sambuc         BT.reset(
62*0a6a1f1dSLionel Sambuc             new BuiltinBug(this, "Cast from non-struct type to struct type",
63f4a2713aSLionel Sambuc                            "Casting a non-structure type to a structure type "
64f4a2713aSLionel Sambuc                            "and accessing a field can lead to memory access "
65f4a2713aSLionel Sambuc                            "errors or data corruption."));
66f4a2713aSLionel Sambuc       BugReport *R = new BugReport(*BT,BT->getDescription(), N);
67f4a2713aSLionel Sambuc       R->addRange(CE->getSourceRange());
68f4a2713aSLionel Sambuc       C.emitReport(R);
69f4a2713aSLionel Sambuc     }
70f4a2713aSLionel Sambuc   }
71f4a2713aSLionel Sambuc }
72f4a2713aSLionel Sambuc 
registerCastToStructChecker(CheckerManager & mgr)73f4a2713aSLionel Sambuc void ento::registerCastToStructChecker(CheckerManager &mgr) {
74f4a2713aSLionel Sambuc   mgr.registerChecker<CastToStructChecker>();
75f4a2713aSLionel Sambuc }
76