Skip to content

fix(streaming): clamp a Range end past EOF instead of marking the file corrupted - #937

Merged
javi11 merged 1 commit into
mainfrom
fix/clamp-range-end-past-eof
Sep 8, 2026
Merged

javi11 merged 1 commit into
mainfrom
fix/clamp-range-end-past-eof

Conversation

@javi11

@javi11 javi11 commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • A legal Range: bytes=N-<past EOF> request (start inside the file, end beyond it — RFC 9110 §14.1.2 says to clamp) reached createUsenetReader unclamped: the WebDAV adapter passes the raw header via context and getRequestRange parsed it without knowing the file size.
  • findSegmentForOffset(end) returned -1 for the out-of-range end, the lazy segment range came back empty, and that emptiness was treated as corrupt metadata: FILE_STATUS_CORRUPTED, and the healthy file then 404'd on WebDAV. Reproduced against a real provider with one curl -r 15000000000-15268435455 on a 15,076,905,867-byte file.
  • Fix: clamp the parsed end to FileSize-1 in getRequestRange; in createUsenetReader return io.EOF for start >= FileSize and clamp end. A genuinely broken segment index still produces the corruption verdict.
  • The import filesystem's identical "No segments to download" path is not affected (its end is always derived from the file's own size).

Test plan

  • TestRangeEndPastEOFIsClampedNotCorrupted — failed before the fix with the production log line, passes after; served bytes equal the file tail, no health record written
  • TestRangeStartAtOrPastEOFIsEOFNotCorruptedRead returns 0, io.EOF, no corruption
  • go vet, go test -race ./internal/nzbfilesystem/... ./internal/importer/filesystem/..., go build ./cmd/altmount

…e corrupted

The WebDAV adapter hands the raw Range header to the file via context and
getRequestRange parsed it without knowing the file size, so a legal
"bytes=N-<past EOF>" request reached createUsenetReader unclamped.
findSegmentForOffset(end) returned -1 for the out-of-range end, the lazy
segment range came back empty, and that emptiness was treated as corrupt
metadata: the file was marked FILE_STATUS_CORRUPTED and vanished from
WebDAV. The parsed end is now clamped to FileSize-1, and createUsenetReader
returns io.EOF for a start at or past EOF and clamps its end, so only a
genuinely broken segment index can still produce the corruption verdict.
@javi11
javi11 merged commit eef9c35 into main Sep 8, 2026
2 checks passed
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.

1 participant