Uploaded image for project: 'MINA SSHD'
  1. MINA SSHD
  2. SSHD-1288

Infinite loop in org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#doRead

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 2.8.0
    • 2.9.1
    • None

    Description

      I reported an  infinite loop  in org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#doRead:

      and after the production of a thread and system dump the  point in execution was:

      private long doRead(long max, BufferConsumer consumer) throws IOException {
          long orgOffset = clientOffset;
          while (max > 0) {
              if (hasNoData()) {
                  if (eofIndicator) {
                      break;
                  }
                  if (!pendingReads.isEmpty()) {
                      fillData();
                  }
                  if (!eofIndicator) {
                      sendRequests(); <- (do not send any request ! it does nothing !)
                  }
              } else {
                  int nb = (int) Math.min(max, buffer.available());
                  consumer.consume(new ByteArrayBuffer(buffer.array(), buffer.rpos(), nb));
                  buffer.rpos(buffer.rpos() + nb);
                  clientOffset += nb;
                  max -= nb;
              }
          }
          return clientOffset - orgOffset;
      }
      

       
      In the system dump it seems the size of file to receive  is obtained before to start the transfer... this size is 82.132.992 bytes; but during the receipt of the data it seems (at the time of the dump) that 82.156.760 was successfully received... this could happen if , during the file receipt, at the remote site the file is written (expanded) with more data.

      ... but when the size of the received data is greater than the original it seems an infinite loop could happen in the org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#doRead when the sendRequests() is invoked to obtain more data (or receive the end of file);

      In the sendRequest():

      while (pendingReads.size() < Math.max(1, windowSize / bufferSize)
             && (fileSize <= 0 || requestOffset < fileSize + bufferSize)) {
             
             ... do the send request to obtain more data (or to receive the end of file)      
              requestOffset += bufferSize;
              }
      

       ... the condition requestOffset < fileSize + bufferSize
      is not satisfied if the requestOffset >= fileSize + bufferSize
      preventing the code from sending a request to receive more data (and/or obtain the end of file) and causing the infinite loop.

      The values of the above variables at time of the dump was:

      ... so that "(fileSize <= 0 || requestOffset < fileSize + bufferSize)" is FALSE

      To reproduce the problem:

      1. create the remote file to receive (1Mb size)
      2. create SftpClient sftp = DefaultSftpClientFactory.NSTANCE.createSftpClient(clientSession)
      3. create InputStream is = sftp.read(file, 32768) end read the inputstrem 4kb at time
      4. stop at the end of while loop block in org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#sendRequests
        when the requestOffset > fileSize
      5. expand the remote file size to 2Mb
      6. remove the stop at point 4 and continue
      7. the code enter into an infinite loop

      Attachments

        1. image-2022-08-05-17-08-55-698.png
          90 kB
          Ivan Fiorentini

        Activity

          People

            twolf Thomas Wolf
            ivanfiorentini Ivan Fiorentini
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 20m
                20m