Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-135791

QModbusClient: : sendRawRequest returns pointer, if delete immediately, QModbusRtuSerialClientPrivate: : onReadyRead function crash

    XMLWordPrintable

Details

    • 3
    • c6452e4ee (dev), 22c21ea88 (6.9), 81be4026a (tqtc/lts-6.8), 46ee510ae (tqtc/lts-6.5)
    • Foundation Sprint 130

    Description

      Here's a short version of the code:

      void  waitFinished (QModbusReply *reply)
      {
          // ...
          
          QModbusRequest modbusRequest(QModbusRequest::MaskWriteRegister, request);
          auto reply = client->sendRawRequest(modbusRequest, macAddr);
          if (!reply) {
              return false;
          }
          if (!reply->isFinished()) {
              QEventLoop loop;
              connect(this, &Engine::sigCancel, &loop, &QEventLoop::quit);
              connect(reply, &QModbusReply::finished, &loop, &QEventLoop::quit);
              loop.exec();
          }
          reply->deleteLater();
          if (cancel_task) {
              LOG_WARN("Task canceled");
              return false;
          }
          
          // do other things...
      } 
      1. If through the initiative to cancel
      2. reply would be deleted
      3. lead to QModbusRtuSerialClientPrivate: : onReadyRead crash because of wild pointer

       

      Qt Code analysis:

      bool QModbusRtuSerialClientPrivate::canMatchRequestAndResponse(const QModbusResponse& response,
                                                                     int sendingServer) const {
          if (m_queue.isEmpty())
              return false;
          const auto& current = m_queue.first();    if (current.reply.isNull())
              return false;  // reply deleted
          if (current.reply->serverAddress() != sendingServer)
              return false;  // server mismatch
          if (current.requestPdu.functionCode() != response.functionCode())
              return false;  // request for different function code
          return true;
      }
      void QModbusRtuSerialClientPrivate::onReadyRead() {
          // ...
          const QModbusResponse response = adu.pdu();
          if (!canMatchRequestAndResponse(response, adu.serverAddress())) {
              qCWarning(QT_MODBUS) << "(RTU client) Cannot match response with open request, "
                                      "ignoring";
              m_queue.first().reply->addIntermediateError(QModbusClient::ResponseRequestMismatch);
              return;
          }
          // ...
      } 
      1. canMatchRequestAndResponse return false, because of "current.reply.isNull()"
      2. in onReadyRead function, no test whether the pointer(m_queue.first().reply) is null
      3. access the pointer m_queue.first().reply directly, Cause a crash

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            ivan.solovev Ivan Solovev
            renn 赵 仁杰
            Vladimir Minenko Vladimir Minenko
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes