Skip to content

Commit caec20f

Browse files
committed
SFTP: retry short writes, fail if stuck
1. Loop WPWRITE until the full chunk is written, advancing the split 64-bit offset with carry. Bail out on error or a zero return and report WOLFSSH_FTP_FAILURE so clients see the truncation instead of a silent success. 2. Update the backup WPWRITE() implemented with fwrite() to parallel the behavior of the backup WPREAD(). Changed to write sz number of 1 byte objects. Issue: F-3880
1 parent a35d1e3 commit caec20f

2 files changed

Lines changed: 41 additions & 15 deletions

File tree

src/wolfsftp.c

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3689,20 +3689,46 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
36893689
return WS_BUFFER_E;
36903690
}
36913691

3692-
ret = WPWRITE(ssh->fs, fd, (byte*)str, strSz, ofst);
3693-
if (ret < 0) {
3694-
#if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH)
3695-
if (ret == NUF_NOSPC) {
3696-
WLOG(WS_LOG_SFTP, "Ran out of memory");
3692+
{
3693+
word32 written = 0;
3694+
3695+
/* Retry while WPWRITE makes forward progress; bail on error
3696+
* or zero return to avoid spinning on a stuck backend. */
3697+
while (written < strSz) {
3698+
ret = WPWRITE(ssh->fs, fd, (byte*)str + written,
3699+
strSz - written, ofst);
3700+
if (ret <= 0) {
3701+
break;
3702+
}
3703+
written += (word32)ret;
3704+
/* Advance the split 64-bit offset, propagating carry. */
3705+
ofst[0] += (word32)ret;
3706+
if (ofst[0] < (word32)ret) {
3707+
ofst[1] += 1;
3708+
}
3709+
}
3710+
3711+
if (ret < 0) {
3712+
#if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH)
3713+
if (ret == NUF_NOSPC) {
3714+
WLOG(WS_LOG_SFTP, "Ran out of memory");
3715+
}
3716+
#endif
3717+
WLOG(WS_LOG_SFTP, "Error writing to file");
3718+
res = err;
3719+
type = WOLFSSH_FTP_FAILURE;
3720+
ret = WS_INVALID_STATE_E;
3721+
}
3722+
else if (written != strSz) {
3723+
WLOG(WS_LOG_SFTP, "Short write: %u of %u bytes",
3724+
written, strSz);
3725+
res = err;
3726+
type = WOLFSSH_FTP_FAILURE;
3727+
ret = WS_INVALID_STATE_E;
3728+
}
3729+
else {
3730+
ret = WS_SUCCESS;
36973731
}
3698-
#endif
3699-
WLOG(WS_LOG_SFTP, "Error writing to file");
3700-
res = err;
3701-
type = WOLFSSH_FTP_FAILURE;
3702-
ret = WS_INVALID_STATE_E;
3703-
}
3704-
else {
3705-
ret = WS_SUCCESS;
37063732
}
37073733
}
37083734

wolfssh/port.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ extern "C" {
11271127
fseek(fd, ofst, 0);
11281128
}
11291129

1130-
return fwrite(buf, sz, 1, fd);
1130+
return fwrite(buf, sizeof(unsigned char), sz, fd);
11311131
}
11321132
#define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
11331133
#endif
@@ -1143,7 +1143,7 @@ extern "C" {
11431143
fseek(fd, ofst, 0);
11441144
}
11451145

1146-
return fread(buf, 1, sz, fd);
1146+
return fread(buf, sizeof(unsigned char), sz, fd);
11471147
}
11481148
#define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
11491149
#endif

0 commit comments

Comments
 (0)