blob: 57ab31803ce080bc9fbbf435be8f6daae600f612 [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
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000016#include "ExprEngineInternalChecks.h"
Argyrios Kyrtzidis98cabba2010-12-22 18:51:49 +000017#include "clang/GR/BugReporter/BugType.h"
18#include "clang/GR/PathSensitive/CheckerVisitor.h"
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000019
20using namespace clang;
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000021using namespace GR;
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000022
23namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000024class PointerSubChecker
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000025 : public CheckerVisitor<PointerSubChecker> {
26 BuiltinBug *BT;
27public:
28 PointerSubChecker() : BT(0) {}
29 static void *getTag();
30 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
31};
32}
33
34void *PointerSubChecker::getTag() {
35 static int x;
36 return &x;
37}
38
39void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
40 const BinaryOperator *B) {
41 // When doing pointer subtraction, if the two pointers do not point to the
42 // same memory chunk, emit a warning.
John McCall2de56d12010-08-25 11:45:40 +000043 if (B->getOpcode() != BO_Sub)
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000044 return;
45
46 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000047 SVal LV = state->getSVal(B->getLHS());
48 SVal RV = state->getSVal(B->getRHS());
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000049
50 const MemRegion *LR = LV.getAsRegion();
51 const MemRegion *RR = RV.getAsRegion();
52
Zhongxing Xuadca2712009-11-10 02:37:53 +000053 if (!(LR && RR))
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000054 return;
55
Zhongxing Xuadca2712009-11-10 02:37:53 +000056 const MemRegion *BaseLR = LR->getBaseRegion();
57 const MemRegion *BaseRR = RR->getBaseRegion();
58
59 if (BaseLR == BaseRR)
60 return;
61
62 // Allow arithmetic on different symbolic regions.
63 if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000064 return;
65
Ted Kremenekd048c6e2010-12-20 21:19:09 +000066 if (ExplodedNode *N = C.generateNode()) {
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000067 if (!BT)
68 BT = new BuiltinBug("Pointer subtraction",
Zhongxing Xudfed7a12009-11-09 07:29:39 +000069 "Subtraction of two pointers that do not point to "
70 "the same memory chunk may cause incorrect result.");
Benjamin Kramerd02e2322009-11-14 12:08:24 +000071 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000072 R->addRange(B->getSourceRange());
73 C.EmitReport(R);
74 }
75}
76
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000077void GR::RegisterPointerSubChecker(ExprEngine &Eng) {
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +000078 Eng.registerCheck(new PointerSubChecker());
79}