Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
2.8.0
-
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:
- create the remote file to receive (1Mb size)
- create SftpClient sftp = DefaultSftpClientFactory.NSTANCE.createSftpClient(clientSession)
- create InputStream is = sftp.read(file, 32768) end read the inputstrem 4kb at time
- stop at the end of while loop block in org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#sendRequests
when the requestOffset > fileSize - expand the remote file size to 2Mb
- remove the stop at point 4 and continue
- the code enter into an infinite loop