コード例 #1
0
void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
                                         CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  // If this is a call to a C++ method, check if the callee is null or
  // undefined.
  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
    SVal V = CC->getCXXThisVal();
    if (V.isUndef()) {
      if (!BT_cxx_call_undef)
        BT_cxx_call_undef.reset(new BuiltinBug("Called C++ object pointer is "
                                               "uninitialized"));
      emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
      return;
    }

    ProgramStateRef StNonNull, StNull;
    llvm::tie(StNonNull, StNull) =
        State->assume(V.castAs<DefinedOrUnknownSVal>());

    if (StNull && !StNonNull) {
      if (!BT_cxx_call_null)
        BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer "
                                              "is null"));
      emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
      return;
    }

    State = StNonNull;
  }

  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const Decl *D = Call.getDecl();
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));

  OwningPtr<BugType> *BT;
  if (isa<ObjCMethodCall>(Call))
    BT = &BT_msg_arg;
  else
    BT = &BT_call_arg;

  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
    if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
                           Call.getArgExpr(i), /*IsFirstArgument=*/i == 0,
                           checkUninitFields, Call, *BT))
      return;

  // If we make it here, record our assumptions about the callee.
  C.addTransition(State);
}
コード例 #2
0
void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
                                         CheckerContext &C) const {
  // If this is a call to a C++ method, check if the callee is null or
  // undefined.
  // FIXME: Generalize this to CXXInstanceCall once it supports
  // getCXXThisVal().
  if (const CXXMemberCall *CC = dyn_cast<CXXMemberCall>(&Call)) {
    SVal V = CC->getCXXThisVal();
    if (V.isUndef()) {
      if (!BT_cxx_call_undef)
        BT_cxx_call_undef.reset(new BuiltinBug("Called C++ object pointer is "
                                               "uninitialized"));
      EmitBadCall(BT_cxx_call_undef.get(), C, CC->getOriginExpr());
      return;
    }
    if (V.isZeroConstant()) {
      if (!BT_cxx_call_null)
        BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer "
                                              "is null"));
      EmitBadCall(BT_cxx_call_null.get(), C, CC->getOriginExpr());
      return;
    }
  }

  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const Decl *D = Call.getDecl();
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));

  OwningPtr<BugType> *BT;
  if (isa<ObjCMethodCall>(Call))
    BT = &BT_msg_arg;
  else
    BT = &BT_call_arg;

  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
    if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
                           Call.getArgExpr(i), /*IsFirstArgument=*/i == 0,
                           checkUninitFields, Call, *BT))
      return;
}
コード例 #3
0
void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
                                                CallOrObjCMessage callOrMsg,
                                                const char *BT_desc,
                                                OwningPtr<BugType> &BT) {
  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const Decl *D = callOrMsg.getDecl();
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() &&
      (D && D->getBody()));
  
  for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
    if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
                           callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
                           checkUninitFields,
                           BT_desc, BT))
      return;
}
コード例 #4
0
void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
                                         CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  // If this is a call to a C++ method, check if the callee is null or
  // undefined.
  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
    SVal V = CC->getCXXThisVal();
    if (V.isUndef()) {
      if (!BT_cxx_call_undef)
        BT_cxx_call_undef.reset(
            new BuiltinBug(this, "Called C++ object pointer is uninitialized"));
      emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
      return;
    }

    ProgramStateRef StNonNull, StNull;
    std::tie(StNonNull, StNull) =
        State->assume(V.castAs<DefinedOrUnknownSVal>());

    if (StNull && !StNonNull) {
      if (!BT_cxx_call_null)
        BT_cxx_call_null.reset(
            new BuiltinBug(this, "Called C++ object pointer is null"));
      emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
      return;
    }

    State = StNonNull;
  }

  const Decl *D = Call.getDecl();
  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
  if (FD) {
    // If we have a declaration, we can make sure we pass enough parameters to
    // the function.
    unsigned Params = FD->getNumParams();
    if (Call.getNumArgs() < Params) {
      ExplodedNode *N = C.generateSink();
      if (!N)
        return;

      LazyInit_BT("Function call with too few arguments", BT_call_few_args);

      SmallString<512> Str;
      llvm::raw_svector_ostream os(Str);
      os << "Function taking " << Params << " argument"
         << (Params == 1 ? "" : "s") << " is called with less ("
         << Call.getNumArgs() << ")";

      C.emitReport(
          llvm::make_unique<BugReport>(*BT_call_few_args, os.str(), N));
    }
  }

  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));

  std::unique_ptr<BugType> *BT;
  if (isa<ObjCMethodCall>(Call))
    BT = &BT_msg_arg;
  else
    BT = &BT_call_arg;

  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
    const ParmVarDecl *ParamDecl = nullptr;
    if(FD && i < FD->getNumParams())
      ParamDecl = FD->getParamDecl(i);
    if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
                           Call.getArgExpr(i), /*IsFirstArgument=*/i == 0,
                           checkUninitFields, Call, *BT, ParamDecl))
      return;
  }

  // If we make it here, record our assumptions about the callee.
  C.addTransition(State);
}