clang  14.0.0git
ReturnPointerRangeChecker.cpp
Go to the documentation of this file.
1 //== ReturnPointerRangeChecker.cpp ------------------------------*- C++ -*--==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines ReturnPointerRangeChecker, which is a path-sensitive check
10 // which looks for an out-of-bound pointer being returned to callers.
11 //
12 //===----------------------------------------------------------------------===//
13 
22 
23 using namespace clang;
24 using namespace ento;
25 
26 namespace {
27 class ReturnPointerRangeChecker :
28  public Checker< check::PreStmt<ReturnStmt> > {
29  mutable std::unique_ptr<BuiltinBug> BT;
30 
31 public:
32  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
33 };
34 }
35 
36 void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
37  CheckerContext &C) const {
38  ProgramStateRef state = C.getState();
39 
40  const Expr *RetE = RS->getRetValue();
41  if (!RetE)
42  return;
43 
44  SVal V = C.getSVal(RetE);
45  const MemRegion *R = V.getAsRegion();
46 
47  const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
48  if (!ER)
49  return;
50 
51  DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
52  // Zero index is always in bound, this also passes ElementRegions created for
53  // pointer casts.
54  if (Idx.isZeroConstant())
55  return;
56 
57  // FIXME: All of this out-of-bounds checking should eventually be refactored
58  // into a common place.
59  DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
60  state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
61 
62  // We assume that the location after the last element in the array is used as
63  // end() iterator. Reporting on these would return too many false positives.
64  if (Idx == ElementCount)
65  return;
66 
67  ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
68  ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
69  if (StOutBound && !StInBound) {
70  ExplodedNode *N = C.generateErrorNode(StOutBound);
71 
72  if (!N)
73  return;
74 
75  // FIXME: This bug correspond to CWE-466. Eventually we should have bug
76  // types explicitly reference such exploit categories (when applicable).
77  if (!BT)
78  BT.reset(new BuiltinBug(
79  this, "Buffer overflow",
80  "Returned pointer value points outside the original object "
81  "(potential buffer overflow)"));
82 
83  // Generate a report for this bug.
84  auto Report =
85  std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
86  Report->addRange(RetE->getSourceRange());
87 
88  const auto ConcreteElementCount = ElementCount.getAs<nonloc::ConcreteInt>();
89  const auto ConcreteIdx = Idx.getAs<nonloc::ConcreteInt>();
90 
91  const auto *DeclR = ER->getSuperRegion()->getAs<DeclRegion>();
92 
93  if (DeclR)
94  Report->addNote("Original object declared here",
95  {DeclR->getDecl(), C.getSourceManager()});
96 
97  if (ConcreteElementCount) {
98  SmallString<128> SBuf;
99  llvm::raw_svector_ostream OS(SBuf);
100  OS << "Original object ";
101  if (DeclR) {
102  OS << "'";
103  DeclR->getDecl()->printName(OS);
104  OS << "' ";
105  }
106  OS << "is an array of " << ConcreteElementCount->getValue() << " '";
107  ER->getValueType().print(OS,
108  PrintingPolicy(C.getASTContext().getLangOpts()));
109  OS << "' objects";
110  if (ConcreteIdx) {
111  OS << ", returned pointer points at index " << ConcreteIdx->getValue();
112  }
113 
114  Report->addNote(SBuf,
115  {RetE, C.getSourceManager(), C.getLocationContext()});
116  }
117 
118  bugreporter::trackExpressionValue(N, RetE, *Report);
119 
120  C.emitReport(std::move(Report));
121  }
122 }
123 
124 void ento::registerReturnPointerRangeChecker(CheckerManager &mgr) {
125  mgr.registerChecker<ReturnPointerRangeChecker>();
126 }
127 
128 bool ento::shouldRegisterReturnPointerRangeChecker(const CheckerManager &mgr) {
129  return true;
130 }
clang::ReturnStmt::getRetValue
Expr * getRetValue()
Definition: Stmt.h:2793
DynamicExtent.h
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::PrintingPolicy
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:59
V
#define V(N, I)
Definition: ASTContext.h:3121
BuiltinCheckerRegistration.h
CheckerManager.h
llvm::SmallString< 128 >
clang::ento::getDynamicElementCount
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
state
and static some checkers Checker The latter are built on top of the former via the Checker and CheckerVisitor and attempts to isolate them from much of the gore of the internal analysis the analyzer is basically a source code simulator that traces out possible paths of execution The state of the and the combination of state and program point is a node in an exploded which has the entry program point and initial state
Definition: README.txt:30
clang::ento::bugreporter::trackExpressionValue
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
BugType.h
BugReporterVisitors.h
CheckerContext.h
Checker.h
ExprEngine.h
clang
Definition: CalledOnceCheck.h:17
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
clang::ReturnStmt
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:2760