194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===--- AttrNonNullChecker.h - 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//
10d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis// This defines AttrNonNullChecker, a builtin check in ExprEngine that
1194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// performs checks for arguments declared to have nonnull attribute.
1294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//
1394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===//
1494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
15bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "ClangSACheckers.h"
16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
17bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
19bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
2194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
2294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xuusing namespace clang;
239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
2494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
25f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremeneknamespace {
26ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass AttrNonNullChecker
27fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  : public Checker< check::PreCall > {
286f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<BugType> BT;
29f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic:
30bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
31fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
32f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek};
33f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace
34f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek
35fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rosevoid AttrNonNullChecker::checkPreCall(const CallEvent &Call,
36bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis                                      CheckerContext &C) const {
37fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const Decl *FD = Call.getDecl();
3894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  if (!FD)
3994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    return;
4094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
41fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
4294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  if (!Att)
4394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    return;
4494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
45fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  ProgramStateRef state = C.getState();
4694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
47fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  // Iterate through the arguments of CE and check them for null.
48fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose  for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx) {
4994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    if (!Att->isNonNull(idx))
5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      continue;
5194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
52fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose    SVal V = Call.getArgSVal(idx);
539a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
549a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose
559a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    // If the value is unknown or undefined, we can't perform this check.
569a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose    if (!DV)
579a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose      continue;
5894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
59bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek    if (!isa<Loc>(*DV)) {
60bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      // If the argument is a union type, we want to handle a potential
61fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      // transparent_union GCC extension.
62fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      const Expr *ArgE = Call.getArgExpr(idx);
63fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      if (!ArgE)
64fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        continue;
65fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
66fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      QualType T = ArgE->getType();
67bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      const RecordType *UT = T->getAsUnionType();
68bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
69bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
70fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose
71bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) {
72bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        nonloc::CompoundVal::iterator CSV_I = CSV->begin();
73bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(CSV_I != CSV->end());
74bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        V = *CSV_I;
75bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        DV = dyn_cast<DefinedSVal>(&V);
76bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        assert(++CSV_I == CSV->end());
77bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        if (!DV)
78bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek          continue;
79fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose      } else {
80bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        // FIXME: Handle LazyCompoundVals?
81bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek        continue;
82bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek      }
83bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek    }
84bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek
8594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    ConstraintManager &CM = C.getConstraintManager();
868bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek    ProgramStateRef stateNotNull, stateNull;
8728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek    llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
8894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
8994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    if (stateNull && !stateNotNull) {
9094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Generate an error node.  Check for a null node in case
9194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // we cache out.
92d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek      if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
9394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
9494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Lazily allocate the BugType object if it hasn't already been
9594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // created. Ownership is transferred to the BugReporter object once
9694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // the BugReport is passed to 'EmitWarning'.
9794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        if (!BT)
98bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis          BT.reset(new BugType("Argument with 'nonnull' attribute passed null",
99bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis                               "API"));
10094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
101e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        BugReport *R =
10250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks          new BugReport(*BT, "Null pointer passed as an argument to a "
10350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks                             "'nonnull' parameter", errorNode);
10494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
10594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Highlight the range of the argument that was null.
106fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        R->addRange(Call.getArgSourceRange(idx));
107fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose        if (const Expr *ArgE = Call.getArgExpr(idx))
108a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose          bugreporter::trackNullOrUndefValue(errorNode, ArgE, *R);
10994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        // Emit the bug report.
11094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu        C.EmitReport(R);
11194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      }
11294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
11394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      // Always return.  Either we cached out or we just emitted an error.
11494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu      return;
11594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    }
11694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
11794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // If a pointer value passed the check we should assume that it is
11894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    // indeed not null from this point forward.
11994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    assert(stateNotNull);
12094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu    state = stateNotNull;
12194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  }
12294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu
12394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If we reach here all of the arguments passed the nonnull check.
12494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu  // If 'state' has been updated generated a new node.
1250bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks  C.addTransition(state);
12694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu}
127bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis
128bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidisvoid ento::registerAttrNonNullChecker(CheckerManager &mgr) {
129bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis  mgr.registerChecker<AttrNonNullChecker>();
130bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis}
131