void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg,
                                                   CheckerContext &C) const {
  
  const Expr *receiver = msg.getInstanceReceiver();
  if (!receiver)
    return;
  
  // FIXME: Enhance with value-tracking information instead of consulting
  // the type of the expression.
  const ObjCObjectPointerType* PT =
    receiver->getType()->getAs<ObjCObjectPointerType>();
  
  if (!PT)
    return;  
  const ObjCInterfaceDecl *OD = PT->getInterfaceDecl();
  if (!OD)
    return;  
  if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
    return;

  if (releaseS.isNull())
    releaseS = GetNullarySelector("release", C.getASTContext());
  // Sending 'release' message?
  if (msg.getSelector() != releaseS)
    return;
                     
  SourceRange R = msg.getSourceRange();

  C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
    "API Upgrade (Apple)",
    "Use -drain instead of -release when using NSAutoreleasePool "
    "and garbage collection", R.getBegin(), &R, 1);
}
Exemplo n.º 2
0
void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
                                                CheckerContext &C) const {

  ProgramStateRef state = C.getState();
  const LocationContext *LCtx = C.getLocationContext();

  // FIXME: Handle 'super'?
  if (const Expr *receiver = msg.getInstanceReceiver()) {
    SVal recVal = state->getSVal(receiver, LCtx);
    if (recVal.isUndef()) {
      if (ExplodedNode *N = C.generateSink()) {
        BugType *BT = 0;
        if (msg.isPureMessageExpr()) {
          if (!BT_msg_undef)
            BT_msg_undef.reset(new BuiltinBug("Receiver in message expression "
                                              "is an uninitialized value"));
          BT = BT_msg_undef.get();
        }
        else {
          if (!BT_objc_prop_undef)
            BT_objc_prop_undef.reset(new BuiltinBug("Property access on an "
                                              "uninitialized object pointer"));
          BT = BT_objc_prop_undef.get();
        }
        BugReport *R =
          new BugReport(*BT, BT->getName(), N);
        R->addRange(receiver->getSourceRange());
        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
                                                                   receiver,
                                                                   R));
        C.EmitReport(R);
      }
      return;
    } else {
      // Bifurcate the state into nil and non-nil ones.
      DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
  
      ProgramStateRef notNilState, nilState;
      llvm::tie(notNilState, nilState) = state->assume(receiverVal);
  
      // Handle receiver must be nil.
      if (nilState && !notNilState) {
        HandleNilReceiver(C, state, msg);
        return;
      }
    }
  }

  const char *bugDesc = msg.isPropertySetter() ?
                     "Argument for property setter is an uninitialized value"
                   : "Argument in message expression is an uninitialized value";
  // Check for any arguments that are uninitialized/undefined.
  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
                      bugDesc, BT_msg_arg);
}
Exemplo n.º 3
0
void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
                                               const ObjCMessage &msg,
                                               ExplodedNode *N) const {

  if (!BT_msg_ret)
    BT_msg_ret.reset(
      new BuiltinBug("Receiver in message expression is "
                     "'nil' and returns a garbage value"));

  llvm::SmallString<200> buf;
  llvm::raw_svector_ostream os(buf);
  os << "The receiver of message '" << msg.getSelector().getAsString()
     << "' is nil and returns a value of type '"
     << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";

  BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
  if (const Expr *receiver = msg.getInstanceReceiver()) {
    report->addRange(receiver->getSourceRange());
    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
                                                                    receiver));
  }
  C.EmitReport(report);
}