Pavel Pohner created SSHD-1181:
----------------------------------

             Summary: SFTP Get downloads empty file from servers which supports 
EOF indication after data
                 Key: SSHD-1181
                 URL: https://issues.apache.org/jira/browse/SSHD-1181
             Project: MINA SSHD
          Issue Type: Bug
    Affects Versions: 2.6.0
            Reporter: Pavel Pohner


So, apparently there's a bug in Mina implementation when downloading the file, 
which is smaller than Mina's buffer (meaning it gets read in one iteration), 
from servers, which send EOF indicator at the end of data 
(https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#[section-9.3|https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-9.3]).

The bug seems to be in setting up EOF indicator in 
{noformat}
org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#pollBuffer{noformat}
prematurely (one iteration sooner), trace with me this example situation - 
download of the small file (14 B):

At some point we arrive to mentioned function _pollBuffer()_, note that 
_this.pendingReads_ is set to 2. In first call of _pollBuffer()_ we go through 
this code on receiving SSH_FXP_DATA
{code:java}
if (type == SftpConstants.SSH_FXP_DATA) {
    int dlen = buf.getInt();
    int rpos = buf.rpos();
    buf.rpos(rpos + dlen);
    Boolean b = SftpHelper.getEndOfFileIndicatorValue(buf, client.getVersion());
    if ((b != null) && b.booleanValue()) {
        eofIndicator = true;
    }{code}
Here, consider this situation, we're downloading file with 14B, remote server 
adds EOF indicator to the end of the data, so it makes 15B, let's add some 
necessary overhead (size etc.) which is, according to my experience, 13B, so we 
receive 15 + 13 = 28B into initial buffer.

Now, if we populate these variables, _dlen_ = 14B (file size), _rpos_ = 13 
(overhead), and we set _buf.rpos_ to 27 (14 + 13), but _wpos_ is at the moment 
equal to 28B, as that's what we received. (We're not taking EOF into account 
here)

Then the _SftpHelper.getEndOfFileIndicatorValue_ is called, which in it's 
implementation looks like this:
{code:java}
public static Boolean getEndOfFileIndicatorValue(Buffer buffer, int version) {
    return (version < SftpConstants.SFTP_V6) || (buffer.available() < 1) ? null 
: buffer.getBoolean();
}
{code}
Pay attention to the _buffer.available()_ function as it's implemented like 
this:
{code:java}
public int available() {
    return wpos - rpos;
}
{code}
therefore returning 1 (28 - 27), condition is then resolved in 
_SftpHelper.getEndOfFileIndicatorValue_ as a true and true is also returned to 
the _pollBuffer_ and _eofIndicator_ is set to true.

If you'd keep tracing further, you'd find out that the buffer is then never 
read and returned from _SftpInputStreamAsync_ class, just because 
_eofIndicator_ was set sooner than it should have been.

 





 



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to