blob: dd6ac7ea84c037f1b43bc3cdec74442af57bd432 [file] [log] [blame]
Zhongxing Xu4f3dc692009-11-09 08:07:38 +00001//=== 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
Zhongxing Xu36897912010-01-20 07:57:45 +000011// cast from non-struct pointer to struct pointer.
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000012// This check corresponds to CWE-588.
13//
14//===----------------------------------------------------------------------===//
15
Ted Kremenek21142582010-12-23 19:38:26 +000016#include "clang/StaticAnalyzer/BugReporter/BugType.h"
17#include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000018#include "ExprEngineInternalChecks.h"
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000019
20using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000021using namespace ento;
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000022
23namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000024class CastToStructChecker
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000025 : public CheckerVisitor<CastToStructChecker> {
26 BuiltinBug *BT;
27public:
28 CastToStructChecker() : BT(0) {}
29 static void *getTag();
30 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
31};
32}
33
34void *CastToStructChecker::getTag() {
35 static int x;
36 return &x;
37}
38
39void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
40 const CastExpr *CE) {
41 const Expr *E = CE->getSubExpr();
42 ASTContext &Ctx = C.getASTContext();
43 QualType OrigTy = Ctx.getCanonicalType(E->getType());
44 QualType ToTy = Ctx.getCanonicalType(CE->getType());
45
46 PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
47 PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
48
49 if (!ToPTy || !OrigPTy)
50 return;
51
52 QualType OrigPointeeTy = OrigPTy->getPointeeType();
53 QualType ToPointeeTy = ToPTy->getPointeeType();
54
Douglas Gregorfb87b892010-04-26 21:31:17 +000055 if (!ToPointeeTy->isStructureOrClassType())
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000056 return;
57
58 // We allow cast from void*.
59 if (OrigPointeeTy->isVoidType())
60 return;
61
62 // Now the cast-to-type is struct pointer, the original type is not void*.
63 if (!OrigPointeeTy->isRecordType()) {
Ted Kremenekd048c6e2010-12-20 21:19:09 +000064 if (ExplodedNode *N = C.generateNode()) {
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000065 if (!BT)
66 BT = new BuiltinBug("Cast from non-struct type to struct type",
67 "Casting a non-structure type to a structure type "
68 "and accessing a field can lead to memory access "
69 "errors or data corruption.");
Benjamin Kramerd02e2322009-11-14 12:08:24 +000070 RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000071 R->addRange(CE->getSourceRange());
72 C.EmitReport(R);
73 }
74 }
75}
76
Ted Kremenek9ef65372010-12-23 07:20:52 +000077void ento::RegisterCastToStructChecker(ExprEngine &Eng) {
Zhongxing Xu4f3dc692009-11-09 08:07:38 +000078 Eng.registerCheck(new CastToStructChecker());
79}