1218887Sdim//== ReturnPointerRangeChecker.cpp ------------------------------*- C++ -*--==// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This file defines ReturnPointerRangeChecker, which is a path-sensitive check 11218887Sdim// which looks for an out-of-bound pointer being returned to callers. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15219077Sdim#include "ClangSACheckers.h" 16249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 18219077Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19219077Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 21218887Sdim 22218887Sdimusing namespace clang; 23218887Sdimusing namespace ento; 24218887Sdim 25218887Sdimnamespace { 26218887Sdimclass ReturnPointerRangeChecker : 27221345Sdim public Checker< check::PreStmt<ReturnStmt> > { 28234353Sdim mutable OwningPtr<BuiltinBug> BT; 29218887Sdimpublic: 30219077Sdim void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; 31218887Sdim}; 32218887Sdim} 33218887Sdim 34219077Sdimvoid ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, 35219077Sdim CheckerContext &C) const { 36234353Sdim ProgramStateRef state = C.getState(); 37218887Sdim 38218887Sdim const Expr *RetE = RS->getRetValue(); 39218887Sdim if (!RetE) 40218887Sdim return; 41218887Sdim 42234353Sdim SVal V = state->getSVal(RetE, C.getLocationContext()); 43218887Sdim const MemRegion *R = V.getAsRegion(); 44218887Sdim 45218887Sdim const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R); 46218887Sdim if (!ER) 47218887Sdim return; 48218887Sdim 49249423Sdim DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); 50218887Sdim // Zero index is always in bound, this also passes ElementRegions created for 51218887Sdim // pointer casts. 52218887Sdim if (Idx.isZeroConstant()) 53218887Sdim return; 54218887Sdim // FIXME: All of this out-of-bounds checking should eventually be refactored 55218887Sdim // into a common place. 56218887Sdim 57218887Sdim DefinedOrUnknownSVal NumElements 58218887Sdim = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), 59218887Sdim ER->getValueType()); 60218887Sdim 61234353Sdim ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true); 62234353Sdim ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false); 63218887Sdim if (StOutBound && !StInBound) { 64218887Sdim ExplodedNode *N = C.generateSink(StOutBound); 65218887Sdim 66218887Sdim if (!N) 67218887Sdim return; 68218887Sdim 69218887Sdim // FIXME: This bug correspond to CWE-466. Eventually we should have bug 70218887Sdim // types explicitly reference such exploit categories (when applicable). 71218887Sdim if (!BT) 72219077Sdim BT.reset(new BuiltinBug("Return of pointer value outside of expected range", 73218887Sdim "Returned pointer value points outside the original object " 74219077Sdim "(potential buffer overflow)")); 75218887Sdim 76218887Sdim // FIXME: It would be nice to eventually make this diagnostic more clear, 77218887Sdim // e.g., by referencing the original declaration or by saying *why* this 78218887Sdim // reference is outside the range. 79218887Sdim 80218887Sdim // Generate a report for this bug. 81226633Sdim BugReport *report = 82226633Sdim new BugReport(*BT, BT->getDescription(), N); 83218887Sdim 84218887Sdim report->addRange(RetE->getSourceRange()); 85243830Sdim C.emitReport(report); 86218887Sdim } 87218887Sdim} 88219077Sdim 89219077Sdimvoid ento::registerReturnPointerRangeChecker(CheckerManager &mgr) { 90219077Sdim mgr.registerChecker<ReturnPointerRangeChecker>(); 91219077Sdim} 92