Skip to content

Fix Windows SFTP open flags and wolfsshd -D argument parsing(f8827) - #1173

Open
miyazakh wants to merge 3 commits into
wolfSSL:masterfrom
miyazakh:f8827_WindowsSFTP
Open

Fix Windows SFTP open flags and wolfsshd -D argument parsing(f8827)#1173
miyazakh wants to merge 3 commits into
wolfSSL:masterfrom
miyazakh:f8827_WindowsSFTP

Conversation

@miyazakh

Copy link
Copy Markdown
Contributor

Summary

  • wolfSSH_SFTP_RecvOpen()'s Windows (USE_WINDOWS_API) path built dwCreationDisposition by OR-ing together OPEN_EXISTING / CREATE_ALWAYS bits, but CreateFile()'s creation-disposition parameter is a single enumerated value, not a bitmask. TRUNC and EXCL were also never wired up (left under #if 0), and APPEND access was missing. Add SFTP_WinCreationDisp() to resolve the SFTP CREAT/EXCL/TRUNC flag combination to the one correct CreateFile() disposition, and OR in FILE_APPEND_DATA for WOLFSSH_FXF_APPEND.
  • wolfsshd's -D (foreground/no-daemon) argument check on Windows compared cmdArgs[i] with WSTRCMP, but cmdArgs entries come from CommandLineToArgvW and are wide strings. Comparing them as narrow char* data meant -D was never recognized. Use wcscmp() against L"-D" instead.
  • Extend the WOLFSSH_TEST_INTERNAL regression-test plumbing in wolfsftp.c/wolfsftp.h to build under USE_WINDOWS_API too (it was previously guarded out on Windows), except for wolfSSH_SFTP_TestInvalidateHeadFd(), which stays POSIX-only since it manipulates a raw fd and Windows tracks a HANDLE instead.
  • Add TestSftpWindowsOpenFlagMatrix() (tests/regress.c), which walks the RecvOpen CREAT/EXCL/TRUNC flag matrix on Windows and checks both the open result and the resulting file state for each case:
    • WRITE only, no CREAT, missing file -> fails, file not created
    • WRITE|CREAT, missing file -> creates it (OPEN_ALWAYS)
    • WRITE|CREAT, existing file -> opens without truncating
    • WRITE|CREAT|TRUNC, existing file -> truncates immediately
    • WRITE|CREAT|EXCL, existing file -> fails
    • WRITE|CREAT|EXCL, missing file -> succeeds
    • READ|WRITE|CREAT, missing file -> creates it

Testing

  • Built and ran the full test suite on Windows via MSYS2 MinGW64 (_WIN32 -> USE_WINDOWS_API):

    PASS: tests/api.test.exe
    PASS: tests/testsuite.test.exe
    PASS: tests/kex.test.exe
    PASS: tests/regress.test.exe
    PASS: tests/unit.test.exe
    

    tests/regress.test.exe includes the new TestSftpWindowsOpenFlagMatrix(), exercising the corrected CreateFile() disposition logic end to end.

  • scripts/external.test and scripts/fwd.test are skipped on Windows as expected (external network / Unix-only port forwarding).

Copilot AI lite review requested due to automatic review settings August 18, 2026 11:10
@miyazakh miyazakh self-assigned this Aug 18, 2026

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

This pull request fixes Windows-specific behavior in wolfSSH’s SFTP server open handling and wolfsshd argument parsing, and adds Windows regression coverage to prevent regressions in the SFTP open-flag matrix.

Changes:

  • Correct Windows SFTP RecvOpen creation-disposition handling by mapping CREAT/EXCL/TRUNC to a single valid CreateFile() disposition and wiring APPEND access.
  • Fix Windows wolfsshd -D detection by comparing CommandLineToArgvW() wide arguments with wcscmp(L"-D").
  • Extend internal SFTP test plumbing to build under USE_WINDOWS_API and add a Windows open-flag matrix regression test.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
wolfssh/wolfsftp.h Enables SFTP internal test hooks on Windows (except POSIX-fd invalidation helper).
src/wolfsftp.c Adds SFTP_WinCreationDisp() and fixes Windows RecvOpen access/disposition handling; adjusts internal test hook gating for Windows.
tests/regress.c Refactors shared SFTP reply assertion helper to build on Windows and adds TestSftpWindowsOpenFlagMatrix().
apps/wolfsshd/wolfsshd.c Fixes -D parsing on Windows by using wcscmp() with wide string literals.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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

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

Comment thread src/wolfsftp.c

@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 #1173

Scan targets checked: wolfssh-bugs, wolfssh-src

Findings: 6
6 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread src/wolfsftp.c
Comment thread tests/regress.c
Comment thread src/wolfsftp.c
Comment thread src/wolfsftp.c
Comment thread apps/wolfsshd/wolfsshd.c
Comment thread tests/regress.c
Comment thread src/wolfsftp.c
Comment thread tests/regress.c
Comment thread src/wolfsftp.c
Comment thread src/wolfsftp.c
Comment thread apps/wolfsshd/wolfsshd.c
Comment thread tests/regress.c
@miyazakh miyazakh assigned wolfSSL-Bot and unassigned miyazakh Aug 20, 2026

@ejohnstown ejohnstown 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.

I sent comments directly.

@philljj philljj 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.

Has merge conficts in src/wolfsftp.c

@philljj philljj assigned miyazakh and unassigned wolfSSL-Bot Aug 26, 2026

@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 #1173

Scan targets checked: wolfssh-bugs, wolfssh-src

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread apps/wolfsshd/wolfsshd.c
argc = (DWORD)cmdArgC;

/* we want the arguments to be normal char strings not wchar_t */
argv = (char**)WMALLOC(argc * sizeof(char*), NULL, DYNTYPE_SSHD);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

argv allocation no longer matches its isDaemon-gated cleanup · Resource leaks on error paths

argv is now allocated in both daemon and -D modes while the cleanup loop at line 3340 is still gated on isDaemon, so -D runs leak argv and every converted argument. That loop also indexes argv when CommandLineToArgvW() fails, since argc now retains the caller's service arg count while argv stays NULL.

Related known finding #8818 (similar but distinct): Both are StartSSHD resource leaks, but the candidate faults in argv cleanup after command-line conversion due to an isDaemon gate/NULL indexing; #8818 faults in the parent-side accepted-connection allocation after fork. The root causes and required cleanup patches differ.

Fix: Gate the cleanup on argv != NULL instead of isDaemon so it runs in both modes and never indexes a NULL array.

Comment thread src/wolfsftp.c
* FILE_WRITE_DATA (granted implicitly by GENERIC_WRITE), so the
* client-supplied offset must be overridden with the current EOF. */
if (isAppend) {
if (GetFileSizeEx(fd, &fileSize) == 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Windows SFTP append resolves EOF non-atomically · Race conditions

The append path captures EOF with GetFileSizeEx() and then writes at that offset, a non-atomic read-modify-write. The file is opened with FILE_SHARE_WRITE, so two appenders resolve the same offset and silently overwrite each other's data, unlike the POSIX O_APPEND path.

Related known finding #8832 (similar but distinct): Both are Windows RecvWrite defects involving WriteFile, but the candidate computes a non-atomic append offset before the write; #8832 accepts a short successful write without checking bytesWritten. They have different root causes and require separate offset versus length-validation patches.

Fix: Set both offset.Offset and offset.OffsetHigh to 0xFFFFFFFF, which WriteFile() treats as an atomic write at end of file.

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.

6 participants