zcov: / lib/Checker/CastToStructChecker.cpp


Files: 1 Branches Taken: 72.2% 13 / 18
Generated: 2010-02-10 01:31 Branches Executed: 88.9% 16 / 18
Line Coverage: 100.0% 29 / 29


Programs: 1 Runs 2897


       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 "clang/Checker/PathSensitive/CheckerVisitor.h"
      17                 : #include "GRExprEngineInternalChecks.h"
      18                 : 
      19                 : using namespace clang;
      20                 : 
      21                 : namespace {
      22                 : class CastToStructChecker 
                     1845: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      23             1845:   : public CheckerVisitor<CastToStructChecker> {
      24                 :   BuiltinBug *BT;
      25                 : public:
      26             1845:   CastToStructChecker() : BT(0) {}
      27                 :   static void *getTag();
      28                 :   void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
      29                 : };
      30                 : }
      31                 : 
      32             1845: void *CastToStructChecker::getTag() {
      33                 :   static int x;
      34             1845:   return &x;
      35                 : }
      36                 : 
      37                 : void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
      38             5771:                                            const CastExpr *CE) {
      39             5771:   const Expr *E = CE->getSubExpr();
      40             5771:   ASTContext &Ctx = C.getASTContext();
      41             5771:   QualType OrigTy = Ctx.getCanonicalType(E->getType());
      42             5771:   QualType ToTy = Ctx.getCanonicalType(CE->getType());
      43                 : 
      44             5771:   PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
      45             5771:   PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
      46                 : 
                     3415: branch 0 taken
                     2356: branch 1 taken
                     2389: branch 2 taken
                     1026: branch 3 taken
      47             5771:   if (!ToPTy || !OrigPTy)
      48             4745:     return;
      49                 : 
      50             1026:   QualType OrigPointeeTy = OrigPTy->getPointeeType();
      51             1026:   QualType ToPointeeTy = ToPTy->getPointeeType();
      52                 : 
                      804: branch 2 taken
                      222: branch 3 taken
      53             1026:   if (!ToPointeeTy->isStructureType())
      54              804:     return;
      55                 : 
      56                 :   // We allow cast from void*.
                      100: branch 2 taken
                      122: branch 3 taken
      57              222:   if (OrigPointeeTy->isVoidType())
      58              100:     return;
      59                 : 
      60                 :   // Now the cast-to-type is struct pointer, the original type is not void*.
                       16: branch 2 taken
                      106: branch 3 taken
      61              122:   if (!OrigPointeeTy->isRecordType()) {
                       16: branch 1 taken
                        0: branch 2 not taken
      62               16:     if (ExplodedNode *N = C.GenerateNode()) {
                       16: branch 0 taken
                        0: branch 1 not taken
      63               16:       if (!BT)
      64                 :         BT = new BuiltinBug("Cast from non-struct type to struct type",
      65                 :                             "Casting a non-structure type to a structure type "
      66                 :                             "and accessing a field can lead to memory access "
      67               16:                             "errors or data corruption.");
      68               16:       RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
      69               16:       R->addRange(CE->getSourceRange());
      70               16:       C.EmitReport(R);
      71                 :     }
      72                 :   }
      73                 : }
      74                 : 
      75             1845: void clang::RegisterCastToStructChecker(GRExprEngine &Eng) {
      76             1845:   Eng.registerCheck(new CastToStructChecker());
      77             1845: }

Generated: 2010-02-10 01:31 by zcov