1 //== ReturnPointerRangeChecker.cpp ------------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines ReturnPointerRangeChecker, which is a path-sensitive check
11 // which looks for an out-of-bound pointer being returned to callers.
13 //===----------------------------------------------------------------------===//
15 #include "GRExprEngineInternalChecks.h"
16 #include "clang/Checker/BugReporter/BugType.h"
17 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
18 #include "clang/Checker/PathSensitive/GRExprEngine.h"
20 using namespace clang;
23 class ReturnPointerRangeChecker :
24 public CheckerVisitor<ReturnPointerRangeChecker> {
27 ReturnPointerRangeChecker() : BT(0) {}
28 static void *getTag();
29 void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
33 void clang::RegisterReturnPointerRangeChecker(GRExprEngine &Eng) {
34 Eng.registerCheck(new ReturnPointerRangeChecker());
37 void *ReturnPointerRangeChecker::getTag() {
38 static int x = 0; return &x;
41 void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
42 const ReturnStmt *RS) {
43 const GRState *state = C.getState();
45 const Expr *RetE = RS->getRetValue();
49 SVal V = state->getSVal(RetE);
50 const MemRegion *R = V.getAsRegion();
58 const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
62 DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
64 // FIXME: All of this out-of-bounds checking should eventually be refactored
65 // into a common place.
67 DefinedOrUnknownSVal NumElements
68 = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
69 ER->getValueType(C.getASTContext()));
71 const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
72 const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
73 if (StOutBound && !StInBound) {
74 ExplodedNode *N = C.GenerateSink(StOutBound);
79 // FIXME: This bug correspond to CWE-466. Eventually we should have bug
80 // types explicitly reference such exploit categories (when applicable).
82 BT = new BuiltinBug("Return of pointer value outside of expected range",
83 "Returned pointer value points outside the original object "
84 "(potential buffer overflow)");
86 // FIXME: It would be nice to eventually make this diagnostic more clear,
87 // e.g., by referencing the original declaration or by saying *why* this
88 // reference is outside the range.
90 // Generate a report for this bug.
91 RangedBugReport *report =
92 new RangedBugReport(*BT, BT->getDescription(), N);
94 report->addRange(RetE->getSourceRange());