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 > {
32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BTAttrNonNull;
33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BugType> BTNullRefArg;
34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
35f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic:
36bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
37fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
38018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
39018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *genReportNullAttrNonNull(const ExplodedNode *ErrorN,
40018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                      const Expr *ArgE) const;
41018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *genReportReferenceToNullPointer(const ExplodedNode *ErrorN,
42018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                             const Expr *ArgE) const;
43f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek};
44f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace
45f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek
4680412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid NonNullParamChecker::checkPreCall(const CallEvent &Call,
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                       CheckerContext &C) const {
48fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const Decl *FD = Call.getDecl();
4994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  if (!FD)
5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    return;
5194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
52fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
5394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
54fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  ProgramStateRef state = C.getState();
5594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
56018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  CallEvent::param_type_iterator TyI = Call.param_type_begin(),
57018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                 TyE = Call.param_type_end();
58018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
59018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx){
60018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
61018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Check if the parameter is a reference. We want to report when reference
62018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // to a null pointer is passed as a paramter.
63018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bool haveRefTypeParam = false;
64018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (TyI != TyE) {
65018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      haveRefTypeParam = (*TyI)->isReferenceType();
66018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      TyI++;
67018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    }
68018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
69018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bool haveAttrNonNull = Att && Att->isNonNull(idx);
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!haveAttrNonNull) {
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Check if the parameter is also marked 'nonnull'.
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ArrayRef<ParmVarDecl*> parms = Call.parameters();
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (idx < parms.size())
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
76018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
77018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (!haveRefTypeParam && !haveAttrNonNull)
7894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      continue;
7994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
80018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // If the value is unknown or undefined, we can't perform this check.
81018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgE = Call.getArgExpr(idx);
82fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose    SVal V = Call.getArgSVal(idx);
83dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie    Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
849a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    if (!DV)
859a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose      continue;
8694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
87018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    // Process the case when the argument is not a location.
88018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    assert(!haveRefTypeParam || DV->getAs<Loc>());
89018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
90018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    if (haveAttrNonNull && !DV->getAs<Loc>()) {
91bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      // If the argument is a union type, we want to handle a potential
92fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      // transparent_union GCC extension.
93fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      if (!ArgE)
94fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        continue;
95fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
96fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      QualType T = ArgE->getType();
97bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      const RecordType *UT = T->getAsUnionType();
98bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
99bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
100fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
101dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie      if (Optional<nonloc::CompoundVal> CSV =
1025251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie              DV->getAs<nonloc::CompoundVal>()) {
103bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        nonloc::CompoundVal::iterator CSV_I = CSV->begin();
104bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(CSV_I != CSV->end());
105bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        V = *CSV_I;
1065251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie        DV = V.getAs<DefinedSVal>();
107bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(++CSV_I == CSV->end());
108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // FIXME: Handle (some_union){ some_other_union_val }, which turns into
109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // a LazyCompoundVal inside a CompoundVal.
110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        if (!V.getAs<Loc>())
11142773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          continue;
11242773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        // Retrieve the corresponding expression.
11342773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks        if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
11442773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks          if (const InitListExpr *IE =
11542773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks                dyn_cast<InitListExpr>(CE->getInitializer()))
11642773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks             ArgE = dyn_cast<Expr>(*(IE->begin()));
11742773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks
118fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      } else {
119bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        // FIXME: Handle LazyCompoundVals?
120bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
121bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      }
122bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek    }
123bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek
12494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    ConstraintManager &CM = C.getConstraintManager();
1258bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek    ProgramStateRef stateNotNull, stateNull;
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
12794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
12894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    if (stateNull && !stateNotNull) {
12994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Generate an error node.  Check for a null node in case
13094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // we cache out.
131d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek      if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
13294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
1336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        BugReport *R = nullptr;
134018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks        if (haveAttrNonNull)
135018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks          R = genReportNullAttrNonNull(errorNode, ArgE);
136018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks        else if (haveRefTypeParam)
137018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks          R = genReportReferenceToNullPointer(errorNode, ArgE);
13894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
13994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Highlight the range of the argument that was null.
140fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        R->addRange(Call.getArgSourceRange(idx));
141018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
14294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Emit the bug report.
143785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose        C.emitReport(R);
14494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      }
14594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
14694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Always return.  Either we cached out or we just emitted an error.
14794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      return;
14894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    }
14994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
15094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // If a pointer value passed the check we should assume that it is
15194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // indeed not null from this point forward.
15294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    assert(stateNotNull);
15394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    state = stateNotNull;
15494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  }
15594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
15694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If we reach here all of the arguments passed the nonnull check.
15794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If 'state' has been updated generated a new node.
1580bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(state);
15994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu}
160bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
16180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportNullAttrNonNull(
162018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  const ExplodedNode *ErrorNode, const Expr *ArgE) const {
163018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // Lazily allocate the BugType object if it hasn't already been
164018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // created. Ownership is transferred to the BugReporter object once
165018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  // the BugReport is passed to 'EmitWarning'.
166018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTAttrNonNull)
167018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    BTAttrNonNull.reset(new BugType(
168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        this, "Argument with 'nonnull' attribute passed null", "API"));
169018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
170018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *R = new BugReport(*BTAttrNonNull,
171018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                  "Null pointer passed as an argument to a 'nonnull' parameter",
172018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                  ErrorNode);
173018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE)
174018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
175018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
176018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
177018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
178018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
17980412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportReferenceToNullPointer(
180018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  const ExplodedNode *ErrorNode, const Expr *ArgE) const {
181018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (!BTNullRefArg)
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
183018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
184018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  BugReport *R = new BugReport(*BTNullRefArg,
185018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                               "Forming reference to null pointer",
186018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                               ErrorNode);
187018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  if (ArgE) {
188018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!ArgEDeref)
190018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks      ArgEDeref = ArgE;
191018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks    bugreporter::trackNullOrUndefValue(ErrorNode,
192018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       ArgEDeref,
193018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks                                       *R);
194018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  }
195018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks  return R;
196018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
197018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks}
198018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks
19980412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid ento::registerNonNullParamChecker(CheckerManager &mgr) {
20080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks  mgr.registerChecker<NonNullParamChecker>();
201bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis}
202