blob: 7c21acc5bee72af01e4163fc44c0502041366403 [file] [log] [blame]
Zhongxing Xuede7eb22009-11-09 13:23:31 +00001//=== PointerArithChecker.cpp - Pointer arithmetic 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 PointerArithChecker, a builtin checker that checks for
11// pointer arithmetic on locations other than array elements.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidis23ade502011-02-15 22:55:20 +000015#include "ClangSACheckers.h"
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000016#include "clang/StaticAnalyzer/Core/Checker.h"
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000017#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000018#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000019#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Zhongxing Xuede7eb22009-11-09 13:23:31 +000020
21using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000022using namespace ento;
Zhongxing Xuede7eb22009-11-09 13:23:31 +000023
24namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000025class PointerArithChecker
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000026 : public Checker< check::PreStmt<BinaryOperator> > {
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000027 mutable llvm::OwningPtr<BuiltinBug> BT;
28
Zhongxing Xuede7eb22009-11-09 13:23:31 +000029public:
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000030 void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
Zhongxing Xuede7eb22009-11-09 13:23:31 +000031};
32}
33
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000034void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
35 CheckerContext &C) const {
John McCall2de56d12010-08-25 11:45:40 +000036 if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
Zhongxing Xuede7eb22009-11-09 13:23:31 +000037 return;
38
39 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000040 SVal LV = state->getSVal(B->getLHS());
41 SVal RV = state->getSVal(B->getRHS());
Zhongxing Xuede7eb22009-11-09 13:23:31 +000042
43 const MemRegion *LR = LV.getAsRegion();
44
45 if (!LR || !RV.isConstant())
46 return;
47
48 // If pointer arithmetic is done on variables of non-array type, this often
49 // means behavior rely on memory organization, which is dangerous.
50 if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
51 isa<CompoundLiteralRegion>(LR)) {
52
Ted Kremenekd048c6e2010-12-20 21:19:09 +000053 if (ExplodedNode *N = C.generateNode()) {
Zhongxing Xuede7eb22009-11-09 13:23:31 +000054 if (!BT)
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000055 BT.reset(new BuiltinBug("Dangerous pointer arithmetic",
Zhongxing Xuede7eb22009-11-09 13:23:31 +000056 "Pointer arithmetic done on non-array variables "
57 "means reliance on memory layout, which is "
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000058 "dangerous."));
Benjamin Kramerd02e2322009-11-14 12:08:24 +000059 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
Zhongxing Xuede7eb22009-11-09 13:23:31 +000060 R->addRange(B->getSourceRange());
61 C.EmitReport(R);
62 }
63 }
64}
65
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000066void ento::registerPointerArithChecker(CheckerManager &mgr) {
Argyrios Kyrtzidis983326f2011-02-23 01:05:36 +000067 mgr.registerChecker<PointerArithChecker>();
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000068}