11053d246f451c399468248625d1146e3d845e21eTed Kremenek//== ReturnUndefChecker.cpp -------------------------------------*- C++ -*--==//
21053d246f451c399468248625d1146e3d845e21eTed Kremenek//
31053d246f451c399468248625d1146e3d845e21eTed Kremenek//                     The LLVM Compiler Infrastructure
41053d246f451c399468248625d1146e3d845e21eTed Kremenek//
51053d246f451c399468248625d1146e3d845e21eTed Kremenek// This file is distributed under the University of Illinois Open Source
61053d246f451c399468248625d1146e3d845e21eTed Kremenek// License. See LICENSE.TXT for details.
71053d246f451c399468248625d1146e3d845e21eTed Kremenek//
81053d246f451c399468248625d1146e3d845e21eTed Kremenek//===----------------------------------------------------------------------===//
91053d246f451c399468248625d1146e3d845e21eTed Kremenek//
101053d246f451c399468248625d1146e3d845e21eTed Kremenek// This file defines ReturnUndefChecker, which is a path-sensitive
111053d246f451c399468248625d1146e3d845e21eTed Kremenek// check which looks for undefined or garbage values being returned to the
121053d246f451c399468248625d1146e3d845e21eTed Kremenek// caller.
131053d246f451c399468248625d1146e3d845e21eTed Kremenek//
141053d246f451c399468248625d1146e3d845e21eTed Kremenek//===----------------------------------------------------------------------===//
151053d246f451c399468248625d1146e3d845e21eTed Kremenek
167f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis#include "ClangSACheckers.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
197f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2016e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
217f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
221053d246f451c399468248625d1146e3d845e21eTed Kremenek
231053d246f451c399468248625d1146e3d845e21eTed Kremenekusing namespace clang;
249ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
251053d246f451c399468248625d1146e3d845e21eTed Kremenek
261053d246f451c399468248625d1146e3d845e21eTed Kremeneknamespace {
27c236b7327f989c1e7fe6b08a188bfef86727513dJordan Roseclass ReturnUndefChecker : public Checker< check::PreStmt<ReturnStmt> > {
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BuiltinBug> BT_Undef;
29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BuiltinBug> BT_NullReference;
30c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
31c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  void emitUndef(CheckerContext &C, const Expr *RetE) const;
32c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  void checkReference(CheckerContext &C, const Expr *RetE,
33c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose                      DefinedOrUnknownSVal RetVal) const;
341053d246f451c399468248625d1146e3d845e21eTed Kremenekpublic:
357f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
361053d246f451c399468248625d1146e3d845e21eTed Kremenek};
371053d246f451c399468248625d1146e3d845e21eTed Kremenek}
381053d246f451c399468248625d1146e3d845e21eTed Kremenek
397f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidisvoid ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
407f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis                                      CheckerContext &C) const {
411053d246f451c399468248625d1146e3d845e21eTed Kremenek  const Expr *RetE = RS->getRetValue();
421053d246f451c399468248625d1146e3d845e21eTed Kremenek  if (!RetE)
431053d246f451c399468248625d1146e3d845e21eTed Kremenek    return;
44c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  SVal RetVal = C.getSVal(RetE);
45c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
4616e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks  const StackFrameContext *SFC = C.getStackFrame();
4716e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks  QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl());
48c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
49c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (RetVal.isUndef()) {
50c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    // "return;" is modeled to evaluate to an UndefinedVal. Allow UndefinedVal
51c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    // to be returned in functions returning void to support this pattern:
52c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //   void foo() {
53c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //     return;
54c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //   }
55c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //   void test() {
56c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //     return foo();
57c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    //   }
58898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    if (!RT.isNull() && RT->isVoidType())
59898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose      return;
60898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose
61898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    // Not all blocks have explicitly-specified return types; if the return type
62898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    // is not available, but the return value expression has 'void' type, assume
63898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    // Sema already checked it.
64898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    if (RT.isNull() && isa<BlockDecl>(SFC->getDecl()) &&
65898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose        RetE->getType()->isVoidType())
66898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose      return;
67898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose
68898be7b4a7b0a527d9bd2569eebc41a198e6e528Jordan Rose    emitUndef(C, RetE);
6916e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks    return;
70c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  }
7116e6a7cb41319459ded69b4d47f405c1035dd347Anna Zaks
72c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (RT.isNull())
73c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    return;
741053d246f451c399468248625d1146e3d845e21eTed Kremenek
75c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (RT->isReferenceType()) {
76c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    checkReference(C, RetE, RetVal.castAs<DefinedOrUnknownSVal>());
77c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    return;
78c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  }
79c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose}
80c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
81c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rosestatic void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    const Expr *TrackingE = nullptr) {
83c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  ExplodedNode *N = C.generateSink();
841053d246f451c399468248625d1146e3d845e21eTed Kremenek  if (!N)
851053d246f451c399468248625d1146e3d845e21eTed Kremenek    return;
86c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
87c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  BugReport *Report = new BugReport(BT, BT.getDescription(), N);
88c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
89c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  Report->addRange(RetE->getSourceRange());
90c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  bugreporter::trackNullOrUndefValue(N, TrackingE ? TrackingE : RetE, *Report);
91c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
92c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  C.emitReport(Report);
93c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose}
94c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
95c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rosevoid ReturnUndefChecker::emitUndef(CheckerContext &C, const Expr *RetE) const {
96c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (!BT_Undef)
97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BT_Undef.reset(
98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        new BuiltinBug(this, "Garbage return value",
99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       "Undefined or garbage value returned to caller"));
100c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  emitBug(C, *BT_Undef, RetE);
101c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose}
102c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
103c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rosevoid ReturnUndefChecker::checkReference(CheckerContext &C, const Expr *RetE,
104c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose                                        DefinedOrUnknownSVal RetVal) const {
105c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  ProgramStateRef StNonNull, StNull;
106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::tie(StNonNull, StNull) = C.getState()->assume(RetVal);
107c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
108c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (StNonNull) {
109c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    // Going forward, assume the location is non-null.
110c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    C.addTransition(StNonNull);
111c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose    return;
112c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  }
113c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
114c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  // The return value is known to be null. Emit a bug report.
115c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  if (!BT_NullReference)
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BT_NullReference.reset(new BuiltinBug(this, "Returning null reference"));
117c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose
118c236b7327f989c1e7fe6b08a188bfef86727513dJordan Rose  emitBug(C, *BT_NullReference, RetE, bugreporter::getDerefExpr(RetE));
1191053d246f451c399468248625d1146e3d845e21eTed Kremenek}
1207f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis
1217f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidisvoid ento::registerReturnUndefChecker(CheckerManager &mgr) {
1227f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis  mgr.registerChecker<ReturnUndefChecker>();
1237f649d749f18b3499456d7ae6a69f3bbd7cf7cdcArgyrios Kyrtzidis}
124