1 //=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "clang/GR/BugReporter/BugType.h"
17 #include "clang/GR/PathSensitive/CheckerVisitor.h"
18 #include "GRExprEngineInternalChecks.h"
20 using namespace clang
;
23 class CastToStructChecker
24 : public CheckerVisitor
<CastToStructChecker
> {
27 CastToStructChecker() : BT(0) {}
28 static void *getTag();
29 void PreVisitCastExpr(CheckerContext
&C
, const CastExpr
*B
);
33 void *CastToStructChecker::getTag() {
38 void CastToStructChecker::PreVisitCastExpr(CheckerContext
&C
,
40 const Expr
*E
= CE
->getSubExpr();
41 ASTContext
&Ctx
= C
.getASTContext();
42 QualType OrigTy
= Ctx
.getCanonicalType(E
->getType());
43 QualType ToTy
= Ctx
.getCanonicalType(CE
->getType());
45 PointerType
*OrigPTy
= dyn_cast
<PointerType
>(OrigTy
.getTypePtr());
46 PointerType
*ToPTy
= dyn_cast
<PointerType
>(ToTy
.getTypePtr());
48 if (!ToPTy
|| !OrigPTy
)
51 QualType OrigPointeeTy
= OrigPTy
->getPointeeType();
52 QualType ToPointeeTy
= ToPTy
->getPointeeType();
54 if (!ToPointeeTy
->isStructureOrClassType())
57 // We allow cast from void*.
58 if (OrigPointeeTy
->isVoidType())
61 // Now the cast-to-type is struct pointer, the original type is not void*.
62 if (!OrigPointeeTy
->isRecordType()) {
63 if (ExplodedNode
*N
= C
.generateNode()) {
65 BT
= new BuiltinBug("Cast from non-struct type to struct type",
66 "Casting a non-structure type to a structure type "
67 "and accessing a field can lead to memory access "
68 "errors or data corruption.");
69 RangedBugReport
*R
= new RangedBugReport(*BT
,BT
->getDescription(), N
);
70 R
->addRange(CE
->getSourceRange());
76 void clang::RegisterCastToStructChecker(GRExprEngine
&Eng
) {
77 Eng
.registerCheck(new CastToStructChecker());