180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//===--- NonNullParamChecker.cpp - Undefined arguments checker -*- C++ -*--===//
294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//                     The LLVM Compiler Infrastructure
494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// This file is distributed under the University of Illinois Open Source
694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// License. See LICENSE.TXT for details.
794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===//
994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
1080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// This defines NonNullParamChecker, which checks for arguments expected not to
1180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// be null due to:
1280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//   - the corresponding parameters being declared to have nonnull attribute
1380412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//   - the corresponding parameters being references; since the call would form
1480412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//     a reference to a null pointer
1594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
1694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===//
1794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
18bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "ClangSACheckers.h"
192fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
21ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
22bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
23f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
24bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
2594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
2694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xuusing namespace clang;
279ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
2894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
29f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremeneknamespace {
3080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksclass NonNullParamChecker
31fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  : public Checker< check::PreCall > {
32018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  mutable OwningPtr<BugType> BTAttrNonNull;
33018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  mutable OwningPtr<BugType> BTNullRefArg;
34f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic:
35bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
36fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
37018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
38018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *genReportNullAttrNonNull(const ExplodedNode *ErrorN,
39018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                      const Expr *ArgE) const;
40018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *genReportReferenceToNullPointer(const ExplodedNode *ErrorN,
41018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                             const Expr *ArgE) const;
42f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek};
43f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace
44f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek
4580412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid NonNullParamChecker::checkPreCall(const CallEvent &Call,
46bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis                                      CheckerContext &C) const {
47fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const Decl *FD = Call.getDecl();
4894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  if (!FD)
4994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    return;
5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
51fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
5294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
53fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  ProgramStateRef state = C.getState();
5494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
55018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  CallEvent::param_type_iterator TyI = Call.param_type_begin(),
56018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                 TyE = Call.param_type_end();
57018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
58018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx){
59018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
60018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Check if the parameter is a reference. We want to report when reference
61018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // to a null pointer is passed as a paramter.
62018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bool haveRefTypeParam = false;
63018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (TyI != TyE) {
64018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      haveRefTypeParam = (*TyI)->isReferenceType();
65018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      TyI++;
66018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    }
67018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
68018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bool haveAttrNonNull = Att && Att->isNonNull(idx);
69018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
70018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (!haveRefTypeParam && !haveAttrNonNull)
7194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      continue;
7294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
73018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // If the value is unknown or undefined, we can't perform this check.
74018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgE = Call.getArgExpr(idx);
75fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose    SVal V = Call.getArgSVal(idx);
76dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie    Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
779a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    if (!DV)
789a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose      continue;
7994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
80018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Process the case when the argument is not a location.
81018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    assert(!haveRefTypeParam || DV->getAs<Loc>());
82018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
83018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (haveAttrNonNull && !DV->getAs<Loc>()) {
84bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      // If the argument is a union type, we want to handle a potential
85fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      // transparent_union GCC extension.
86fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      if (!ArgE)
87fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        continue;
88fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
89fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      QualType T = ArgE->getType();
90bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      const RecordType *UT = T->getAsUnionType();
91bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
92bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
93fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
94dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie      if (Optional<nonloc::CompoundVal> CSV =
955251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie              DV->getAs<nonloc::CompoundVal>()) {
96bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        nonloc::CompoundVal::iterator CSV_I = CSV->begin();
97bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(CSV_I != CSV->end());
98bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        V = *CSV_I;
995251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie        DV = V.getAs<DefinedSVal>();
100bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(++CSV_I == CSV->end());
101bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        if (!DV)
10242773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          continue;
10342773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        // Retrieve the corresponding expression.
10442773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
10542773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          if (const InitListExpr *IE =
10642773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks                dyn_cast<InitListExpr>(CE->getInitializer()))
10742773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks             ArgE = dyn_cast<Expr>(*(IE->begin()));
10842773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks
109fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      } else {
110bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        // FIXME: Handle LazyCompoundVals?
111bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
112bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      }
113bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek    }
114bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek
11594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    ConstraintManager &CM = C.getConstraintManager();
1168bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek    ProgramStateRef stateNotNull, stateNull;
11728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek    llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
11894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
11994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    if (stateNull && !stateNotNull) {
12094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Generate an error node.  Check for a null node in case
12194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // we cache out.
122d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek      if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
12394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
124018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks        BugReport *R = 0;
125018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks        if (haveAttrNonNull)
126018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks          R = genReportNullAttrNonNull(errorNode, ArgE);
127018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks        else if (haveRefTypeParam)
128018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks          R = genReportReferenceToNullPointer(errorNode, ArgE);
12994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
13094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Highlight the range of the argument that was null.
131fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        R->addRange(Call.getArgSourceRange(idx));
132018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
13394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Emit the bug report.
134785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose        C.emitReport(R);
13594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      }
13694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
13794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Always return.  Either we cached out or we just emitted an error.
13894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      return;
13994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    }
14094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
14194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // If a pointer value passed the check we should assume that it is
14294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // indeed not null from this point forward.
14394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    assert(stateNotNull);
14494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    state = stateNotNull;
14594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  }
14694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
14794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If we reach here all of the arguments passed the nonnull check.
14894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If 'state' has been updated generated a new node.
1490bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(state);
15094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu}
151bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
15280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportNullAttrNonNull(
153018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  const ExplodedNode *ErrorNode, const Expr *ArgE) const {
154018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // Lazily allocate the BugType object if it hasn't already been
155018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // created. Ownership is transferred to the BugReporter object once
156018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // the BugReport is passed to 'EmitWarning'.
157018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTAttrNonNull)
158018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    BTAttrNonNull.reset(new BugType(
159018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                            "Argument with 'nonnull' attribute passed null",
160018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                            "API"));
161018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
162018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *R = new BugReport(*BTAttrNonNull,
163018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                  "Null pointer passed as an argument to a 'nonnull' parameter",
164018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                  ErrorNode);
165018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE)
166018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
167018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
168018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
169018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
170018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
17180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportReferenceToNullPointer(
172018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  const ExplodedNode *ErrorNode, const Expr *ArgE) const {
173018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTNullRefArg)
174018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    BTNullRefArg.reset(new BuiltinBug("Dereference of null pointer"));
175018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
176018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *R = new BugReport(*BTNullRefArg,
177018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                               "Forming reference to null pointer",
178018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                               ErrorNode);
179018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE) {
180018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
181018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (ArgEDeref == 0)
182018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      ArgEDeref = ArgE;
183018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode,
184018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       ArgEDeref,
185018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       *R);
186018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  }
187018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
188018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
189018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
190018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
19180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid ento::registerNonNullParamChecker(CheckerManager &mgr) {
19280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks  mgr.registerChecker<NonNullParamChecker>();
193bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis}
194