Skip to content

port: resolve the full SFTP offset in the Harmony and Zephyr ports - #1172

Open
yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/f_8823HZ
Open

port: resolve the full SFTP offset in the Harmony and Zephyr ports#1172
yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/f_8823HZ

Conversation

@yosuke-wolfssl

@yosuke-wolfssl yosuke-wolfssl commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Problem

wPread() / wPwrite() receive the SFTP file offset as two 32-bit words, low
word first, and SFTP_Read / SFTP_Write propagate carry into the high word.
The Harmony and Zephyr ports seeked with shortOffset[0] alone, silently
masking any offset at or past 4 GiB — an SFTP client reading past that boundary
gets data from the wrong part of the file, and a write corrupts it. PR #1166
fixed the two POSIX ports and added the shared helper; these are the next two
ports in that sequence.

Fix (src/port.c, wolfssh/port.h)

Both ports now assemble the offset with wResolveOffset() before seeking:

  • Harmony resolves against WOLFSSH_MAX_FILE_OFFSET, then casts to
    int32_t for SYS_FS_FileSeek. The existing WFSEEK_SUCCESS check is
    unchanged.
  • Zephyr resolves before taking z_fds_mutex and casts to off_t for
    fs_seek, replacing the word32* cast of shortOffset. The fd-range check,
    mutex discipline, and seek return check are unchanged.

The Harmony block also defines WOLFSSH_MAX_FILE_OFFSET as 0x7FFFFFFF, ahead
of the off_t-derived default, so the ceiling comes from SYS_FS_FileSeek's
int32_t parameter rather than from a type this port never uses. It keeps the
#ifndef guard, so the macro stays user-overridable like the rest of port.h.

An offset above the ceiling now returns -1, surfacing as
WOLFSSH_FTP_FAILURE for that one request instead of truncating silently.

Nucleus, the fseek fallback, and FATFS are intentionally not in this PR —
each also needs a sequential-position or unchecked-return fix beyond the helper.

Tests (tests/unit.c)

test_PreadPwriteHighOffset() needs mkstemp and a 4 GiB sparse file, so it
excludes both ports. Two tests replace that coverage:

  • test_ResolveOffset() checks the shared helper directly — offset
    assembly from both words, the accepted and rejected sides of the ceiling, and
    the NULL guards. It takes maxOffset as a parameter, so it needs no
    filesystem and runs in the ordinary Linux and macOS jobs.
  • test_PreadPwriteOffsetCeiling() exercises the Zephyr port end to end on
    the sample's 64 KiB RAM disk: write at offset 0, read back at offset 8 to
    confirm the resolved offset reaches the seek, then confirm a read and a write
    at exactly 4 GiB both fail.

Verification

  • Preflight sweep clean under gcc-13 -Werror: all 6 configs.
  • Zephyr twister on qemu_x86, 3/3 scenarios passed. Reverting the fix fails 2 of
    3; forcing fs_seek to offset 0 also fails, so the read back has teeth.
  • test_ResolveOffset() kills three helper mutants: > changed to >=, the
    high word dropped, and the comparison replaced by shortOffset[1] != 0.
  • Harmony has no CI, so src/port.c was compiled against Microchip's generated
    sys_fs.h and driven by a host harness: 0x100 and 0x7FFFFFFF reach the
    seek unchanged, 2 GiB and 4 GiB are rejected without seeking. Reverting the
    fix makes the 4 GiB case seek to 0.

Closes f-8823 for these two ports.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Aug 17, 2026
Copilot AI lite review requested due to automatic review settings August 17, 2026 00:30

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 incorrect SFTP read/write behavior at offsets ≥ 4 GiB by ensuring the Harmony and Zephyr filesystem ports assemble and validate the full 64-bit (hi/lo) SFTP offset before seeking, preventing silent truncation to the low 32 bits.

Changes:

  • Update Harmony and Zephyr wPread()/wPwrite() implementations to resolve the split offset via wResolveOffset() before seeking.
  • Add a Zephyr-only unit test that verifies offsets at exactly 4 GiB are rejected when the port’s seek type cannot represent them.

Reviewed changes

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

File Description
src/port.c Uses wResolveOffset() before seeking in Harmony and Zephyr ports to avoid dropping the high offset word.
tests/unit.c Adds a Zephyr-gated unit test that exercises the “offset ceiling rejection” path at 4 GiB.
Suppressed comments (1)

src/port.c:153

  • Same issue as wPwrite(): Harmony seeks with a signed 32-bit offset, so validating against WOLFSSH_MAX_FILE_OFFSET (based on off_t) can allow offsets that will later be truncated by the (int32_t) cast. Guard with an explicit 32-bit maximum for SYS_FS_FileSeek.
            if (wResolveOffset(shortOffset, WOLFSSH_MAX_FILE_OFFSET,
                        &offset) == 0) {

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

Comment thread src/port.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 #1172

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. Findings are non-blocking.

Comment thread tests/unit.c
Comment thread tests/unit.c
Comment thread tests/unit.c
Comment thread tests/unit.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 #1172

Scan targets checked: wolfssh-bugs, wolfssh-src

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

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

Comment thread tests/unit.c
- Assemble the split offset with wResolveOffset() in the Harmony wPread
  and wPwrite, and seek with the resolved value.
- Assemble the split offset with wResolveOffset() in the Zephyr wPread
  and wPwrite, and seek with the resolved value.
- Define WOLFSSH_MAX_FILE_OFFSET as 0x7FFFFFFF in the Harmony block, so
  the ceiling comes from SYS_FS_FileSeek's int32_t offset rather than
  from off_t.
- Add test_PreadPwriteOffsetCeiling() covering ports whose seek type
  cannot reach 4 GiB, including a read back at an in-range offset.
- Add test_ResolveOffset() covering offset assembly, both sides of the
  ceiling, and the NULL guards.

Issue: F-8823
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