clang API Documentation
00001 //=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This files defines PointerArithChecker, a builtin checker that checks for 00011 // pointer arithmetic on locations other than array elements. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "ClangSACheckers.h" 00016 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 00017 #include "clang/StaticAnalyzer/Core/Checker.h" 00018 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 namespace { 00025 class PointerArithChecker 00026 : public Checker< check::PreStmt<BinaryOperator> > { 00027 mutable std::unique_ptr<BuiltinBug> BT; 00028 00029 public: 00030 void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 00031 }; 00032 } 00033 00034 void PointerArithChecker::checkPreStmt(const BinaryOperator *B, 00035 CheckerContext &C) const { 00036 if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add) 00037 return; 00038 00039 ProgramStateRef state = C.getState(); 00040 const LocationContext *LCtx = C.getLocationContext(); 00041 SVal LV = state->getSVal(B->getLHS(), LCtx); 00042 SVal RV = state->getSVal(B->getRHS(), LCtx); 00043 00044 const MemRegion *LR = LV.getAsRegion(); 00045 00046 if (!LR || !RV.isConstant()) 00047 return; 00048 00049 // If pointer arithmetic is done on variables of non-array type, this often 00050 // means behavior rely on memory organization, which is dangerous. 00051 if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) || 00052 isa<CompoundLiteralRegion>(LR)) { 00053 00054 if (ExplodedNode *N = C.addTransition()) { 00055 if (!BT) 00056 BT.reset( 00057 new BuiltinBug(this, "Dangerous pointer arithmetic", 00058 "Pointer arithmetic done on non-array variables " 00059 "means reliance on memory layout, which is " 00060 "dangerous.")); 00061 BugReport *R = new BugReport(*BT, BT->getDescription(), N); 00062 R->addRange(B->getSourceRange()); 00063 C.emitReport(R); 00064 } 00065 } 00066 } 00067 00068 void ento::registerPointerArithChecker(CheckerManager &mgr) { 00069 mgr.registerChecker<PointerArithChecker>(); 00070 }