xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This files defines PointerArithChecker, a builtin checker that checks for
11f4a2713aSLionel Sambuc // pointer arithmetic on locations other than array elements.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "ClangSACheckers.h"
16f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h"
18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20f4a2713aSLionel Sambuc 
21f4a2713aSLionel Sambuc using namespace clang;
22f4a2713aSLionel Sambuc using namespace ento;
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc namespace {
25f4a2713aSLionel Sambuc class PointerArithChecker
26f4a2713aSLionel Sambuc   : public Checker< check::PreStmt<BinaryOperator> > {
27*0a6a1f1dSLionel Sambuc   mutable std::unique_ptr<BuiltinBug> BT;
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc public:
30f4a2713aSLionel Sambuc   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
31f4a2713aSLionel Sambuc };
32f4a2713aSLionel Sambuc }
33f4a2713aSLionel Sambuc 
checkPreStmt(const BinaryOperator * B,CheckerContext & C) const34f4a2713aSLionel Sambuc void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
35f4a2713aSLionel Sambuc                                        CheckerContext &C) const {
36f4a2713aSLionel Sambuc   if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
37f4a2713aSLionel Sambuc     return;
38f4a2713aSLionel Sambuc 
39f4a2713aSLionel Sambuc   ProgramStateRef state = C.getState();
40f4a2713aSLionel Sambuc   const LocationContext *LCtx = C.getLocationContext();
41f4a2713aSLionel Sambuc   SVal LV = state->getSVal(B->getLHS(), LCtx);
42f4a2713aSLionel Sambuc   SVal RV = state->getSVal(B->getRHS(), LCtx);
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc   const MemRegion *LR = LV.getAsRegion();
45f4a2713aSLionel Sambuc 
46f4a2713aSLionel Sambuc   if (!LR || !RV.isConstant())
47f4a2713aSLionel Sambuc     return;
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc   // If pointer arithmetic is done on variables of non-array type, this often
50f4a2713aSLionel Sambuc   // means behavior rely on memory organization, which is dangerous.
51f4a2713aSLionel Sambuc   if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
52f4a2713aSLionel Sambuc       isa<CompoundLiteralRegion>(LR)) {
53f4a2713aSLionel Sambuc 
54f4a2713aSLionel Sambuc     if (ExplodedNode *N = C.addTransition()) {
55f4a2713aSLionel Sambuc       if (!BT)
56*0a6a1f1dSLionel Sambuc         BT.reset(
57*0a6a1f1dSLionel Sambuc             new BuiltinBug(this, "Dangerous pointer arithmetic",
58f4a2713aSLionel Sambuc                            "Pointer arithmetic done on non-array variables "
59f4a2713aSLionel Sambuc                            "means reliance on memory layout, which is "
60f4a2713aSLionel Sambuc                            "dangerous."));
61f4a2713aSLionel Sambuc       BugReport *R = new BugReport(*BT, BT->getDescription(), N);
62f4a2713aSLionel Sambuc       R->addRange(B->getSourceRange());
63f4a2713aSLionel Sambuc       C.emitReport(R);
64f4a2713aSLionel Sambuc     }
65f4a2713aSLionel Sambuc   }
66f4a2713aSLionel Sambuc }
67f4a2713aSLionel Sambuc 
registerPointerArithChecker(CheckerManager & mgr)68f4a2713aSLionel Sambuc void ento::registerPointerArithChecker(CheckerManager &mgr) {
69f4a2713aSLionel Sambuc   mgr.registerChecker<PointerArithChecker>();
70f4a2713aSLionel Sambuc }
71