-
Notifications
You must be signed in to change notification settings - Fork 104
Fix window handling for extended data and add a test #936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9842,13 +9842,17 @@ static int DoChannelExtendedData(WOLFSSH* ssh, | |
| channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF); | ||
| if (channel == NULL) | ||
| ret = WS_INVALID_CHANID; | ||
| else if (dataSz > channel->windowSz) { | ||
| WLOG(WS_LOG_ERROR, "Internal state error, too much data"); | ||
| ret = WS_RECV_OVERFLOW_E; | ||
| } | ||
| else { | ||
| ret = PutBuffer(&ssh->extDataBuffer, buf + begin, dataSz); | ||
| ret = PutBuffer(&ssh->extDataBuffer, buf + begin, dataSz); | ||
| #ifdef DEBUG_WOLFSSH | ||
| DumpOctetString(buf + begin, dataSz); | ||
| #endif | ||
| if (ret == WS_SUCCESS) { | ||
| ret = SendChannelWindowAdjust(ssh, channel->channel, dataSz); | ||
| channel->windowSz -= dataSz; | ||
| } | ||
|
Comment on lines
+9850
to
9856
|
||
| } | ||
| *idx = begin + dataSz; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1327,6 +1327,12 @@ int wolfSSH_extended_data_read(WOLFSSH* ssh, byte* out, word32 outSz) | |||||||||||||||||||||||||
| buf = ssh->extDataBuffer.buffer + ssh->extDataBuffer.idx; | ||||||||||||||||||||||||||
| WMEMCPY(out, buf, bufSz); | ||||||||||||||||||||||||||
| ssh->extDataBuffer.idx += bufSz; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (bufSz > 0 && ssh->channelList != NULL) { | ||||||||||||||||||||||||||
| SendChannelWindowAdjust(ssh, ssh->channelList->channel, bufSz); | ||||||||||||||||||||||||||
| ssh->channelList->windowSz += bufSz; | ||||||||||||||||||||||||||
|
Comment on lines
+1332
to
+1333
|
||||||||||||||||||||||||||
| SendChannelWindowAdjust(ssh, ssh->channelList->channel, bufSz); | |
| ssh->channelList->windowSz += bufSz; | |
| if (ssh->channelList->channel == ssh->lastRxId) { | |
| SendChannelWindowAdjust(ssh, ssh->channelList->channel, bufSz); | |
| ssh->channelList->windowSz += bufSz; | |
| } | |
| else { | |
| WLOG(WS_LOG_ERROR, | |
| "Extended data channel mismatch: pending data is for channel %u," | |
| " current channelList head is %u", | |
| ssh->lastRxId, ssh->channelList->channel); | |
| } |
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wolfSSH_extended_data_read() sends a CHANNEL_WINDOW_ADJUST but ignores the return code. In non-blocking mode SendChannelWindowAdjust() can return WS_WANT_WRITE/WS_WANT_READ (or other errors); currently this function will still return bufSz and unconditionally increment windowSz, which can desync local window accounting and hides I/O errors from the caller. Capture the send result, only increment windowSz when the adjust message was successfully queued/sent, and propagate/set ssh->error on failure (similar to _ChannelRead/_UpdateChannelWindow).
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -52,6 +52,17 @@ | |||||
| #ifndef WOLFSSH_TEST_BLOCK | ||||||
| #define WOLFSSH_TEST_HEX2BIN | ||||||
| #endif | ||||||
| #ifndef SINGLE_THREADED | ||||||
| #ifndef WOLFSSH_TEST_LOCKING | ||||||
| #define WOLFSSH_TEST_LOCKING | ||||||
| #endif | ||||||
| #ifndef WOLFSSH_TEST_SERVER | ||||||
| #define WOLFSSH_TEST_SERVER | ||||||
| #endif | ||||||
| #ifndef WOLFSSH_TEST_THREADING | ||||||
| #define WOLFSSH_TEST_THREADING | ||||||
| #endif | ||||||
| #endif | ||||||
| #include <wolfssh/test.h> | ||||||
| #include "tests/api.h" | ||||||
|
|
||||||
|
|
@@ -2013,6 +2024,213 @@ static void test_wolfSSH_KeyboardInteractive(void) { ; } | |||||
| #endif /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */ | ||||||
| #endif /* WOLFSSH_KEYBOARD_INTERACTIVE */ | ||||||
|
|
||||||
| /* Extended data (SSH_MSG_CHANNEL_EXTENDED_DATA) window management test. | ||||||
| * Verifies DoChannelExtendedData decrements the channel window and | ||||||
| * wolfSSH_extended_data_read restores it via SendChannelWindowAdjust. */ | ||||||
| #if !defined(SINGLE_THREADED) && !defined(NO_WOLFSSH_CLIENT) && \ | ||||||
| !defined(NO_FILESYSTEM) | ||||||
|
||||||
| !defined(NO_FILESYSTEM) | |
| !defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new dataSz > channel->windowSz check returns WS_RECV_OVERFLOW_E, while the analogous check for regular data in ChannelPutData() treats this as an internal/protocol-fatal condition (WS_FATAL_ERROR). Since this path logs "Internal state error", consider aligning the error code with ChannelPutData() to keep error semantics consistent for window violations.