Skip to content

scp: fix duplicate file header on send - #1128

Open
ejohnstown wants to merge 2 commits into
wolfSSL:masterfrom
ejohnstown:fix-scp-dupe-header
Open

scp: fix duplicate file header on send#1128
ejohnstown wants to merge 2 commits into
wolfSSL:masterfrom
ejohnstown:fix-scp-dupe-header

Conversation

@ejohnstown

Copy link
Copy Markdown
Contributor
  • Gate header on new scpFileHeaderSent flag, not scpFileOffset==0
  • A send callback returning 0 bytes first no longer re-sends header
  • Skip zero-length SCP_SEND_FILE send to avoid empty CHANNEL_DATA
  • Reset offset/bufferedSz/flag in ScpSourceInit for connection reuse
  • Add test_wolfSSH_SCP_SendZeroFirst regression (func_args scp_send hook)

Issue: ZD-22176

Copilot AI review requested due to automatic review settings July 23, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an SCP server-side edge case where the file header could be transmitted more than once when the SCP send callback returns 0 bytes on its first invocation, and adds a regression test by allowing tests to inject a custom SCP send callback into the echoserver harness.

Changes:

  • Add scpFileHeaderSent state to gate header emission per file (instead of relying on scpFileOffset == 0).
  • Avoid emitting zero-length CHANNEL_DATA when the send buffer is empty, and reset SCP per-file state on source init / connection reuse paths.
  • Add test_wolfSSH_SCP_SendZeroFirst regression test and enable callback injection via func_args.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
wolfssh/test.h Includes wolfscp.h under WOLFSSH_SCP and extends func_args with an injectable scp_send callback.
wolfssh/internal.h Adds scpFileHeaderSent to SCP state tracked on the WOLFSSH object.
tests/api.c Adds a regression test ensuring a 0-byte-first send callback does not cause a duplicated SCP file header.
src/wolfscp.c Uses scpFileHeaderSent to gate header sending, skips zero-length sends, and resets per-file state for reuse.
src/internal.c Initializes scpFileHeaderSent during SSH session initialization.
examples/echoserver/echoserver.c Applies an injected SCP send callback to the server context for tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/wolfscp.c
@ejohnstown
ejohnstown force-pushed the fix-scp-dupe-header branch from e0d32bb to ec84812 Compare July 23, 2026 22:54
- Gate header on new scpFileHeaderSent flag, not scpFileOffset==0
- A send callback returning 0 bytes first no longer re-sends header
- Skip zero-length SCP_SEND_FILE send to avoid empty CHANNEL_DATA
- Abort on a second consecutive 0-byte send callback return with file
  data outstanding; skipping the send would otherwise spin
  SCP_SEND_FILE -> SCP_TRANSFER with no socket I/O
- Reset offset/bufferedSz/flags in ScpSourceInit for connection reuse
- Document the WS_CallbackScpSend contract, including when a 0 return
  is valid, next to the typedef
- Add test_wolfSSH_SCP_SendZeroFirst regression (func_args scp_send hook)
- Zero func_args in kex.c/testsuite.c so the new scp_send field is not read uninitialized

Issue: ZD-22176
@ejohnstown
ejohnstown force-pushed the fix-scp-dupe-header branch from ec84812 to 59cd208 Compare July 30, 2026 22:54
- Track the scpFileName allocation size in a new scpFileNameCap field,
  so GetScpFileName() and ScpCheckForRename() reuse the buffer whenever
  the name plus its terminator fits, instead of testing against the
  previous name length
- Pass scpFileNameCap to the send callback, which writes into
  scpFileName and needs the capacity; scpFileNameSz is now the name
  length on every path, including the source path
- Free and reallocate the transfer buffer in ScpSourceInit(), clearing
  the size fields alongside the pointers they describe
- Wrap a long line in ScpProcessEntry()
- Add test_ScpGetFileName covering the reuse-vs-realloc branch, the
  exact-fit boundary, a grow-by-one that catches an off-by-one in the
  reuse condition, and a source-path buffer holding no name yet
- Add test_wolfSSH_SCP_RecursiveTwoFiles, a real "scp -r" transfer of
  two files, covering the scpFileHeaderSent reset on the recursive
  path added in the duplicate-header fix; it clears leftovers from an
  aborted run up front and bounds its recv so a regression fails
  instead of hanging. Not built on Windows, where a recursive transfer
  through the default callbacks does not reproduce the sent file

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1128

Scan targets checked: wolfssh-bugs, wolfssh-src

No new issues found in the changed files. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants