1381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- C++ -*-//
2381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//
3381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//                     The LLVM Compiler Infrastructure
4381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//
5381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// This file is distributed under the University of Illinois Open Source
6381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// License. See LICENSE.TXT for details.
7381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//
8381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
9381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//
10381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// This defines UnixAPIChecker, which is an assortment of checks on calls
11381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// to various, widely used UNIX/Posix functions.
12381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//
13381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
14381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
15027a6abdd6cedc0b8203da72eed6d15c796dce9dArgyrios Kyrtzidis#include "ClangSACheckers.h"
1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/TargetInfo.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
19695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
2166d5142ab5026aa77ab6f1d7e4d9bdb0b438d55aTed Kremenek#include "llvm/ADT/Optional.h"
2200bd44d5677783527d7517c1ffe45e4d75a0f56fBenjamin Kramer#include "llvm/ADT/STLExtras.h"
2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h"
24381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek#include "llvm/ADT/StringSwitch.h"
25a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
26381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek#include <fcntl.h>
27381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
28381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenekusing namespace clang;
299ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
30381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
31381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremeneknamespace {
32ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
34983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  mutable Optional<uint64_t> Val_O_CREAT;
35bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek
36bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenekpublic:
37983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
38af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose
39af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
40af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
41c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
42af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
43c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
44eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose  void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const;
453e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
463e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
47af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose
48af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
49af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose                                             const CallExpr *) const;
50c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenekprivate:
51c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  bool ReportZeroByteAllocation(CheckerContext &C,
528bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                ProgramStateRef falseState,
53c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                const Expr *arg,
54c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                const char *fn_name) const;
553e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  void BasicAllocationCheck(CheckerContext &C,
563e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                            const CallExpr *CE,
573e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                            const unsigned numArgs,
583e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                            const unsigned sizeArg,
593e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                            const char *fn) const;
60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void LazyInitialize(std::unique_ptr<BugType> &BT, const char *name) const {
61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (BT)
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return;
63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BT.reset(new BugType(this, name, categories::UnixAPI));
64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
65176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void ReportOpenBug(CheckerContext &C,
66176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                     ProgramStateRef State,
67176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                     const char *Msg,
68176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                     SourceRange SR) const;
69381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek};
70381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek} //end anonymous namespace
71381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
72381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
73381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// "open" (man 2 open)
74381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
75381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
76176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesvoid UnixAPIChecker::ReportOpenBug(CheckerContext &C,
77176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   ProgramStateRef State,
78176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   const char *Msg,
79176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   SourceRange SR) const {
8087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ExplodedNode *N = C.generateErrorNode(State);
81176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!N)
82176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return;
83176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
84176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  LazyInitialize(BT_open, "Improper use of 'open'");
85176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
8687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto Report = llvm::make_unique<BugReport>(*BT_open, Msg, N);
87176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  Report->addRange(SR);
8887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  C.emitReport(std::move(Report));
89176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
90176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
91af5b043fe7933e515e405b8509b2609117045ce7Jordy Rosevoid UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  ProgramStateRef state = C.getState();
93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (CE->getNumArgs() < 2) {
95176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // The frontend should issue a warning for this case, so this is a sanity
96176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // check.
97176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return;
98176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  } else if (CE->getNumArgs() == 3) {
99176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const Expr *Arg = CE->getArg(2);
100176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    QualType QT = Arg->getType();
101176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!QT->isIntegerType()) {
102176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ReportOpenBug(C, state,
103176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                    "Third argument to 'open' is not an integer",
104176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                    Arg->getSourceRange());
105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return;
106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
107176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  } else if (CE->getNumArgs() > 3) {
108176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ReportOpenBug(C, state,
109176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  "Call to 'open' with more than three arguments",
110176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  CE->getArg(3)->getSourceRange());
111176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return;
112176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
113176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
114bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek  // The definition of O_CREAT is platform specific.  We need a better way
115bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek  // of querying this information from the checking environment.
116af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  if (!Val_O_CREAT.hasValue()) {
11787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (C.getASTContext().getTargetInfo().getTriple().getVendor()
118bcfd1f55bfbb3e5944cd5e03d07b343e280838c4Douglas Gregor                                                      == llvm::Triple::Apple)
119af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose      Val_O_CREAT = 0x0200;
120bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek    else {
121bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek      // FIXME: We need a more general way of getting the O_CREAT value.
122bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek      // We could possibly grovel through the preprocessor state, but
123d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis      // that would require passing the Preprocessor object to the ExprEngine.
124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // See also: MallocChecker.cpp / M_ZERO.
125bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek      return;
126bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek    }
127bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek  }
128bace4ba042d87a0ed0ec15dbe6caad946b97bd33Ted Kremenek
129381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  // Now check if oflags has O_CREAT set.
130381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  const Expr *oflagsEx = CE->getArg(1);
1315eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
1325251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie  if (!V.getAs<NonLoc>()) {
133381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    // The case where 'V' can be a location can only be due to a bad header,
134381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    // so in this case bail out.
135381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    return;
136381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  }
1375251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie  NonLoc oflags = V.castAs<NonLoc>();
1385251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie  NonLoc ocreateFlag = C.getSValBuilder()
1395251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie      .makeIntVal(Val_O_CREAT.getValue(), oflagsEx->getType()).castAs<NonLoc>();
1409c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
141846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek                                                      oflags, ocreateFlag,
142846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek                                                      oflagsEx->getType());
143381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  if (maskedFlagsUC.isUnknownOrUndef())
144381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    return;
1455251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie  DefinedSVal maskedFlags = maskedFlagsUC.castAs<DefinedSVal>();
146381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
147381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  // Check if maskedFlags is non-zero.
1488bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef trueState, falseState;
149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::tie(trueState, falseState) = state->assume(maskedFlags);
150381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
151381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  // Only emit an error if the value of 'maskedFlags' is properly
152381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  // constrained;
153381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  if (!(trueState && !falseState))
154381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    return;
155381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
156381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  if (CE->getNumArgs() < 3) {
157176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ReportOpenBug(C, trueState,
158176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  "Call to 'open' requires a third argument when "
159176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  "the 'O_CREAT' flag is set",
160176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  oflagsEx->getSourceRange());
161381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek  }
162381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek}
163381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
164381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
16599d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek// pthread_once
16699d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek//===----------------------------------------------------------------------===//
16799d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
168af5b043fe7933e515e405b8509b2609117045ce7Jordy Rosevoid UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
169af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose                                      const CallExpr *CE) const {
17099d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
17199d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
17299d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  // They can possibly be refactored.
17399d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
17499d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  if (CE->getNumArgs() < 1)
17599d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    return;
17699d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
17799d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  // Check if the first argument is stack allocated.  If so, issue a warning
17899d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  // because that's likely to be bad news.
1798bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
1805eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  const MemRegion *R =
1815eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
18299d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
18399d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    return;
18499d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ExplodedNode *N = C.generateErrorNode(state);
18699d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  if (!N)
18799d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    return;
18899d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
189f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> S;
19099d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  llvm::raw_svector_ostream os(S);
19199d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  os << "Call to 'pthread_once' uses";
19299d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  if (const VarRegion *VR = dyn_cast<VarRegion>(R))
19399d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    os << " the local variable '" << VR->getDecl()->getName() << '\'';
19499d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  else
19599d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    os << " stack allocated memory";
19699d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  os << " for the \"control\" value.  Using such transient memory for "
19799d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  "the control value is potentially dangerous.";
19899d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
19999d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek    os << "  Perhaps you intended to declare the variable as 'static'?";
20099d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
201af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  LazyInitialize(BT_pthreadOnce, "Improper use of 'pthread_once'");
202af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose
20387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto report = llvm::make_unique<BugReport>(*BT_pthreadOnce, os.str(), N);
20499d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek  report->addRange(CE->getArg(0)->getSourceRange());
20587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  C.emitReport(std::move(report));
20699d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek}
20799d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek
20899d9838b256ded8e59f85c93647ba5ec060b7145Ted Kremenek//===----------------------------------------------------------------------===//
209eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose// "calloc", "malloc", "realloc", "reallocf", "alloca" and "valloc"
210eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose// with allocation size 0
211b12fbc216f77bd309f8c416834b341ff43325aabTed Kremenek//===----------------------------------------------------------------------===//
2123e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek// FIXME: Eventually these should be rolled into the MallocChecker, but right now
2133e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek// they're more basic and valuable for widespread use.
214b12fbc216f77bd309f8c416834b341ff43325aabTed Kremenek
215c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek// Returns true if we try to do a zero byte allocation, false otherwise.
216c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek// Fills in trueState and falseState.
2178bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekstatic bool IsZeroByteAllocation(ProgramStateRef state,
218c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                const SVal argVal,
2198bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                ProgramStateRef *trueState,
2208bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                ProgramStateRef *falseState) {
221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::tie(*trueState, *falseState) =
2225251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie    state->assume(argVal.castAs<DefinedSVal>());
22387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
224c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  return (*falseState && !*trueState);
225c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek}
226c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
227c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek// Generates an error report, indicating that the function whose name is given
228c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek// will perform a zero byte allocation.
229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Returns false if an error occurred, true otherwise.
230c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenekbool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
2318bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                              ProgramStateRef falseState,
232c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                              const Expr *arg,
233c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                              const char *fn_name) const {
23487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ExplodedNode *N = C.generateErrorNode(falseState);
235c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  if (!N)
236c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    return false;
237c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
2383e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  LazyInitialize(BT_mallocZero,
239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                 "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
240c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
241f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> S;
24287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  llvm::raw_svector_ostream os(S);
243c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
24487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
245c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
246c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  report->addRange(arg->getSourceRange());
247a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose  bugreporter::trackNullOrUndefValue(N, arg, *report);
24887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  C.emitReport(std::move(report));
249c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
250c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  return true;
251c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek}
252c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
2533e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek// Does a basic check for 0-sized allocations suitable for most of the below
2543e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek// functions (modulo "calloc")
2553e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenekvoid UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
2563e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                          const CallExpr *CE,
2573e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                          const unsigned numArgs,
2583e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                          const unsigned sizeArg,
2593e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                          const char *fn) const {
2603e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  // Sanity check for the correct number of arguments
2613e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  if (CE->getNumArgs() != numArgs)
2623e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek    return;
2633e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek
2643e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  // Check if the allocation size is 0.
2658bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
2666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ProgramStateRef trueState = nullptr, falseState = nullptr;
2673e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  const Expr *arg = CE->getArg(sizeArg);
2683e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  SVal argVal = state->getSVal(arg, C.getLocationContext());
2693e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek
2703e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  if (argVal.isUnknownOrUndef())
2713e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek    return;
2723e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek
2733e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  // Is the value perfectly constrained to zero?
2743e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
27587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    (void) ReportZeroByteAllocation(C, falseState, arg, fn);
2763e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek    return;
2773e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  }
278bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru  // Assume the value is non-zero going forward.
2793e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  assert(trueState);
2803e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  if (trueState != state)
28187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    C.addTransition(trueState);
2823e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek}
2833e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek
284c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenekvoid UnixAPIChecker::CheckCallocZero(CheckerContext &C,
285c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                     const CallExpr *CE) const {
286c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  unsigned int nArgs = CE->getNumArgs();
287c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  if (nArgs != 2)
288c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    return;
289c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
2908bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
2916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ProgramStateRef trueState = nullptr, falseState = nullptr;
292c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
293c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  unsigned int i;
294c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  for (i = 0; i < nArgs; i++) {
295c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    const Expr *arg = CE->getArg(i);
2965eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    SVal argVal = state->getSVal(arg, C.getLocationContext());
297c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    if (argVal.isUnknownOrUndef()) {
298c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      if (i == 0)
299c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek        continue;
300c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      else
301c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek        return;
302c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    }
303c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
304c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
305c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
306c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek        return;
307c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      else if (i == 0)
308c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek        continue;
309c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      else
310c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek        return;
311c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    }
312c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  }
313c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
314bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru  // Assume the value is non-zero going forward.
315c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  assert(trueState);
316c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek  if (trueState != state)
317c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek    C.addTransition(trueState);
318c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek}
319c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
320af5b043fe7933e515e405b8509b2609117045ce7Jordy Rosevoid UnixAPIChecker::CheckMallocZero(CheckerContext &C,
321af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose                                     const CallExpr *CE) const {
3223e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  BasicAllocationCheck(C, CE, 1, 0, "malloc");
323c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek}
324c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
325c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenekvoid UnixAPIChecker::CheckReallocZero(CheckerContext &C,
326c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek                                      const CallExpr *CE) const {
3273e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  BasicAllocationCheck(C, CE, 2, 1, "realloc");
3283e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek}
329c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
330eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rosevoid UnixAPIChecker::CheckReallocfZero(CheckerContext &C,
331eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose                                       const CallExpr *CE) const {
332eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose  BasicAllocationCheck(C, CE, 2, 1, "reallocf");
333eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose}
334eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose
3353e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenekvoid UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
3363e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                     const CallExpr *CE) const {
3373e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  BasicAllocationCheck(C, CE, 1, 0, "alloca");
3383e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek}
339c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
3403e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenekvoid UnixAPIChecker::CheckVallocZero(CheckerContext &C,
3413e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                     const CallExpr *CE) const {
3423e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek  BasicAllocationCheck(C, CE, 1, 0, "valloc");
3433e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek}
344c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
345c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek
346b12fbc216f77bd309f8c416834b341ff43325aabTed Kremenek//===----------------------------------------------------------------------===//
347381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek// Central dispatch function.
348381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek//===----------------------------------------------------------------------===//
349381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
3503e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenekvoid UnixAPIChecker::checkPreStmt(const CallExpr *CE,
3513e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek                                  CheckerContext &C) const {
3525ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose  const FunctionDecl *FD = C.getCalleeDecl(CE);
3535ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose  if (!FD || FD->getKind() != Decl::Function)
3545ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose    return;
3555ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose
3565ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose  StringRef FName = C.getCalleeName(FD);
357b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks  if (FName.empty())
358381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek    return;
359381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek
360af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  SubChecker SC =
361b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks    llvm::StringSwitch<SubChecker>(FName)
362af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose      .Case("open", &UnixAPIChecker::CheckOpen)
363af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose      .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
364c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      .Case("calloc", &UnixAPIChecker::CheckCallocZero)
365af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose      .Case("malloc", &UnixAPIChecker::CheckMallocZero)
366c1275da4eb5778eb3c9600e79918ad1fbec589c6Ted Kremenek      .Case("realloc", &UnixAPIChecker::CheckReallocZero)
367eafaad279f7be4552e5a2246fcda1b5d65698104Jordan Rose      .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
3683e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek      .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
3693e97758f22f31d0dbc336fc4794b86aed8607053Ted Kremenek      .Case("valloc", &UnixAPIChecker::CheckVallocZero)
3706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      .Default(nullptr);
371af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose
372af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose  if (SC)
373af5b043fe7933e515e405b8509b2609117045ce7Jordy Rose    (this->*SC)(C, CE);
374381d1bf0eeabccac1ba64909cad73d2ee963897bTed Kremenek}
375983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis
376983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
377983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis// Registration.
378983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
379983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis
380983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidisvoid ento::registerUnixAPIChecker(CheckerManager &mgr) {
381983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  mgr.registerChecker<UnixAPIChecker>();
382983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis}
383