Fix SendPacketType to not advance state when negotiation fails

SendPacketType() set the state to SFTP_SEND_PACKET even when
wolfSSH_SFTP_negotiate() returned a retry or an error. No request
buffer was built in that case, so an empty buffer was sent and the
caller could wait for a response to a request that was never sent.

Move to SFTP_SEND_PACKET only when the request has been
built, and return the negotiation result otherwise. Keep the state
for retryable errors.

Add the wolfSSH_TestSftpSendPacketType() test hook and an API test
that fails without this change.

F-13904
pull/1312/head
ouki 2026-10-11 15:53:34 +09:00 committed by John Safranek
parent 91cb9aded4
commit c8e2eddb36
3 changed files with 47 additions and 1 deletions

View File

@ -711,6 +711,15 @@ int wolfSSH_TestSftpRecvSizeCheck(int sz)
{
return SFTP_CheckRecvSz(sz);
}
/* Test hook: exposes the static SendPacketType() so the unit tests can
* check that no request is sent when SFTP negotiation did not succeed. */
int wolfSSH_TestSftpSendPacketType(WOLFSSH* ssh, byte type, byte* buf,
word32 bufSz)
{
return SendPacketType(ssh, type, buf, bufSz);
}
#endif
@ -6905,8 +6914,15 @@ int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz)
/* reset state for sending data */
wolfSSH_SFTP_buffer_rewind(&state->buffer);
state->state = SFTP_SEND_PACKET;
}
state->state = SFTP_SEND_PACKET;
else {
if(!NoticeError(ssh)){
wolfSSH_SFTP_ClearState(ssh, STATE_ID_SEND);
}
return ret;
}
FALL_THROUGH;
case SFTP_SEND_PACKET:

View File

@ -6267,6 +6267,32 @@ static void test_wolfSSH_SFTP_SaveOfst(void)
}
/* SendPacketType must not send a request when negotiation did not succeed */
static void test_wolfSSH_SFTP_SendPacketType_negotiate(void)
{
#ifdef WOLFSSH_TEST_INTERNAL
WOLFSSH_CTX* ctx = NULL;
WOLFSSH* ssh = NULL;
byte payload[4] = { 0x00, 0x01, 0x02, 0x03 };
int ret;
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
ret = wolfSSH_TestSftpSendPacketType(ssh, WOLFSSH_FTP_REALPATH,
payload, (word32)sizeof(payload));
/* The SFTP connection was not established, so negotiation cannot succeed.
* SendPacketType() must report that failure instead of returning WS_SUCCESS */
AssertIntNE(ret, WS_SUCCESS);
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
#endif /* WOLFSSH_TEST_INTERNAL */
}
#if !defined(NO_FILESYSTEM) && !defined(WOLFSSH_USER_FILESYSTEM) && \
!defined(WOLFSSH_ZEPHYR)
@ -6690,6 +6716,7 @@ static void test_wolfSSH_SFTP_StartPathNotConfined(void) { ; }
static void test_wolfSSH_SFTP_SetConfinePath(void) { ; }
static void test_wolfSSH_SFTP_SetDefaultPath(void) { ; }
static void test_wolfSSH_SFTP_SaveOfst(void) { ; }
static void test_wolfSSH_SFTP_SendPacketType_negotiate(void) { ; }
static void test_wolfSSH_SFTP_PutResume(void) { ; }
static void test_wolfSSH_SFTP_GetResume(void) { ; }
#endif /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */
@ -8823,6 +8850,7 @@ int wolfSSH_ApiTest(int argc, char** argv)
test_wolfSSH_SFTP_SetConfinePath();
test_wolfSSH_SFTP_SetDefaultPath();
test_wolfSSH_SFTP_SaveOfst();
test_wolfSSH_SFTP_SendPacketType_negotiate();
test_wolfSSH_SFTP_PutResume();
test_wolfSSH_SFTP_GetResume();

View File

@ -360,6 +360,8 @@ WOLFSSH_LOCAL void wolfSSH_SFTP_ShowSizes(void);
WS_SFTP_FILEATRB* atr, word32* idx);
WOLFSSH_API int wolfSSH_TestSftpSendCap(WOLFSSH* ssh, word32 cap);
WOLFSSH_API int wolfSSH_TestSftpStallPending(WOLFSSH* ssh, word32 count);
WOLFSSH_API int wolfSSH_TestSftpSendPacketType(WOLFSSH* ssh, byte type,
byte* buf, word32 bufSz);
#if !defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
WOLFSSH_API int wolfSSH_SFTP_TestRecvStateInit(WOLFSSH* ssh);
WOLFSSH_API const byte* wolfSSH_SFTP_TestRecvReply(WOLFSSH* ssh,