]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Analysis/PointerSubChecker.cpp
Update clang to r94309.
[FreeBSD/FreeBSD.git] / lib / Analysis / PointerSubChecker.cpp
1 //=== PointerSubChecker.cpp - Pointer subtraction 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 PointerSubChecker, a builtin checker that checks for
11 // pointer subtractions on two pointers pointing to different memory chunks. 
12 // This check corresponds to CWE-469.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "clang/Analysis/PathSensitive/CheckerVisitor.h"
17 #include "GRExprEngineInternalChecks.h"
18
19 using namespace clang;
20
21 namespace {
22 class PointerSubChecker 
23   : public CheckerVisitor<PointerSubChecker> {
24   BuiltinBug *BT;
25 public:
26   PointerSubChecker() : BT(0) {}
27   static void *getTag();
28   void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
29 };
30 }
31
32 void *PointerSubChecker::getTag() {
33   static int x;
34   return &x;
35 }
36
37 void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
38                                                const BinaryOperator *B) {
39   // When doing pointer subtraction, if the two pointers do not point to the
40   // same memory chunk, emit a warning.
41   if (B->getOpcode() != BinaryOperator::Sub)
42     return;
43
44   const GRState *state = C.getState();
45   SVal LV = state->getSVal(B->getLHS());
46   SVal RV = state->getSVal(B->getRHS());
47
48   const MemRegion *LR = LV.getAsRegion();
49   const MemRegion *RR = RV.getAsRegion();
50
51   if (!(LR && RR))
52     return;
53
54   const MemRegion *BaseLR = LR->getBaseRegion();
55   const MemRegion *BaseRR = RR->getBaseRegion();
56
57   if (BaseLR == BaseRR)
58     return;
59
60   // Allow arithmetic on different symbolic regions.
61   if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
62     return;
63
64   if (ExplodedNode *N = C.GenerateNode()) {
65     if (!BT)
66       BT = new BuiltinBug("Pointer subtraction", 
67                           "Subtraction of two pointers that do not point to "
68                           "the same memory chunk may cause incorrect result.");
69     RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
70     R->addRange(B->getSourceRange());
71     C.EmitReport(R);
72   }
73 }
74
75 void clang::RegisterPointerSubChecker(GRExprEngine &Eng) {
76   Eng.registerCheck(new PointerSubChecker());
77 }