blob: e86710a0c5555a7dff7645bae1f6254d8486ef4f [file] [log] [blame]
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +00001//=== 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
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000016#include "GRExprEngineInternalChecks.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000017#include "clang/Checker/BugReporter/BugType.h"
18#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000019
20using namespace clang;
21
22namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000023class PointerSubChecker
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000024 : public CheckerVisitor<PointerSubChecker> {
25 BuiltinBug *BT;
26public:
27 PointerSubChecker() : BT(0) {}
28 static void *getTag();
29 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
30};
31}
32
33void *PointerSubChecker::getTag() {
34 static int x;
35 return &x;
36}
37
38void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
39 const BinaryOperator *B) {
40 // When doing pointer subtraction, if the two pointers do not point to the
41 // same memory chunk, emit a warning.
John McCall2de56d12010-08-25 11:45:40 +000042 if (B->getOpcode() != BO_Sub)
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000043 return;
44
45 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000046 SVal LV = state->getSVal(B->getLHS());
47 SVal RV = state->getSVal(B->getRHS());
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000048
49 const MemRegion *LR = LV.getAsRegion();
50 const MemRegion *RR = RV.getAsRegion();
51
Zhongxing Xuadca2712009-11-10 02:37:53 +000052 if (!(LR && RR))
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000053 return;
54
Zhongxing Xuadca2712009-11-10 02:37:53 +000055 const MemRegion *BaseLR = LR->getBaseRegion();
56 const MemRegion *BaseRR = RR->getBaseRegion();
57
58 if (BaseLR == BaseRR)
59 return;
60
61 // Allow arithmetic on different symbolic regions.
62 if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000063 return;
64
Ted Kremenekd048c6e2010-12-20 21:19:09 +000065 if (ExplodedNode *N = C.generateNode()) {
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000066 if (!BT)
67 BT = new BuiltinBug("Pointer subtraction",
Zhongxing Xudfed7a12009-11-09 07:29:39 +000068 "Subtraction of two pointers that do not point to "
69 "the same memory chunk may cause incorrect result.");
Benjamin Kramerd02e2322009-11-14 12:08:24 +000070 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000071 R->addRange(B->getSourceRange());
72 C.EmitReport(R);
73 }
74}
75
76void clang::RegisterPointerSubChecker(GRExprEngine &Eng) {
77 Eng.registerCheck(new PointerSubChecker());
78}