Skip to content

Wrong range with negative range (breaks RFC 7233) #1628

Description

@Starmania

Describe the bug

copyparty ignores suffix byte ranges (Range: bytes=-N). Instead of returning the last N bytes, it treats the absent first-byte-pos as 0 and reuses N as the last-byte-pos, so it returns the first N+1 bytes — with a 206 Partial Content and a Content-Range that claims the range it actually served.

This violates RFC 7233 §2.1 (suffix-byte-range-spec), and it is worse than a plain 416: the client gets a success status and self-consistent headers, so it has no way to notice it received the head of the file instead of the tail. Anything that reads trailing metadata over HTTP is silently fed the wrong bytes — remote zip readers (end-of-central-directory), log tailers, media containers with a trailing index.

To Reproduce

Serve any file (example below is 19381087 bytes) and request a suffix range:

Request Response Content-Range Should be
bytes=-10 bytes 0-10/19381087 last 10 bytes
bytes=-100 bytes 0-100/19381087 last 100 bytes
bytes=-65536 bytes 0-65536/19381087 last 65536 bytes
curl -si -H 'Range: bytes=-10' http://127.0.0.1:3923/somefile.bin | head -n1
curl -si -H 'Range: bytes=-10' http://127.0.0.1:3923/somefile.bin | grep -i content-range

Expected behavior

bytes=-N returns the final N bytes: Content-Range: bytes 102390-102399/102400, Content-Length: 10.

Per RFC 7233 §2.1, if N is larger than the file, the whole file is returned (not 416). bytes=-0 is unsatisfiable and should be 416.

Explicit ranges are unaffected and already correct (bytes=19381077-19381086 works, so does bytes=102390-).

Expected behavior

bytes=-N returns the final N bytes: for the file above, Content-Range: bytes 102390-102399/102400 with Content-Length: 10.

Per RFC 7233 §2.1, a suffix length larger than the file returns the whole file (not 416). bytes=-0 is unsatisfiable and should stay 416.

Server details (if you're NOT using docker/podman)

  • server OS / version: Ubuntu 24.04.4 LTS, Linux 7.0.0-29-generic x86_64
  • what copyparty did you grab: run from source, 9de0902
  • how you're running it: in a terminal
  • --version:
copyparty v1.20.21 "sftp is fine too" (2026-08-17)
  CPython v3.12.3 on Linux64 24.04.2 [GCC 13.3.0]
   sqlite 3.45.1*1 | jinja 3.1.2 | pyftpd (None) | tftp (None) | miko (None)
  • copyparty arguments and/or config-file: -p 3923 -v .::r

Client details

curl

The rest of the stack

None

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions