Skip to content

fix: Avoid panics when content is longer than content length header#8

Open
konstin wants to merge 3 commits intomainfrom
konsti/bounds-checks
Open

fix: Avoid panics when content is longer than content length header#8
konstin wants to merge 3 commits intomainfrom
konsti/bounds-checks

Conversation

@konstin
Copy link
Member

@konstin konstin commented Mar 5, 2026

Fixes astral-sh/uv#18316

This fix handles two cases:

  • The server sends more bytes than initially promised in the Content-Length header
  • The server sends more or less bytes than the content-range indicated

As a side effect, we remove the requirement that the initial response must be towards the end (-len:).

@konstin konstin requested a review from EliteTK March 5, 2026 22:31
@konstin konstin changed the title Avoid panics when content is longer than content length header fix: Avoid panics when content is longer than content length header Mar 5, 2026
@konstin konstin force-pushed the konsti/bounds-checks branch from d55f528 to 461909f Compare March 6, 2026 12:19
Fixes astral-sh/uv#18316

This fix handles two cases:
* The server sends more bytes than initially promised in the `Content-Length` header
* The server sends more or less bytes than the `content-range` indicated

As a side effect, we remove the requirement that the initial response must be towards the end (`-len:`).
@konstin konstin force-pushed the konsti/bounds-checks branch from 461909f to bba9d11 Compare March 6, 2026 12:44
@konstin konstin marked this pull request as ready for review March 6, 2026 12:44
Copy link

@EliteTK EliteTK left a comment

Choose a reason for hiding this comment

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

I believe this would fix it. Can't see any fundamental problems with this fix aside from https://github.com/astral-sh/async_http_range_reader/pull/8/changes#r2902785393.

But I feel there are a few improvements which could be made to the error handling.

When we encounter this error in uv, do we switch to just normal non-range requests? If not, it might need a follow up PR for that since it wouldn't be a good fix if instead of panicking we just error in this case without trying the slow path.

There is an argument to be made that for the case in astral-sh/uv#18316, since the range we get back covers the entire memory map, we could just accept it. It would fill the memory map and our reads can just return from this memory map with no further requests.

I guess then we can't warn users about this, although I am not sure if it's useful to be noisy about warning about this anyway...

Comment on lines -537 to +551
offset = byte_range.end;
offset += bytes.len() as u64;
Copy link

Choose a reason for hiding this comment

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

nit: I liked the previous version of this line better :)

Copy link
Member Author

Choose a reason for hiding this comment

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

oh 😅

src/lib.rs Outdated
if offset > end_exclusive {
state.error = Some(AsyncHttpRangeReaderError::ContentLengthMismatch {
expected: end_exclusive - start,
actual: offset - start,
Copy link

Choose a reason for hiding this comment

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

This isn't quite true. The actual content length if the response is chunked and there's no content length header is unknowable. And regardless, if there is a content length, that's what the actual content length would be.

let _ = state_tx.send(state);
break 'outer;
}

Copy link

Choose a reason for hiding this comment

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

About here is where we should check that the response's range header matches what we requested.

This would catch the case where a server replies with a range of the right size, but at the wrong offset, which would be a mangled reply, but still entirely possible.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added

konstin and others added 2 commits March 9, 2026 11:45
Co-authored-by: Tomasz Kramkowski <tomasz@kramkow.ski>
@konstin
Copy link
Member Author

konstin commented Mar 9, 2026

When we encounter this error in uv, do we switch to just normal non-range requests? If not, it might need a follow up PR for that since it wouldn't be a good fix if instead of panicking we just error in this case without trying the slow path.

I guess then we can't warn users about this, although I am not sure if it's useful to be noisy about warning about this anyway...

We match on the upstream error type: https://github.com/astral-sh/uv/blob/401661ee22048d98a0e58c3be9bf3fd2d162e062/crates/uv-client/src/error.rs#L245. We have to extend this, I would at least make the error loud, there's something really bad going on with the user's server and they get a severe performance degradation due to that, that they'd otherwise attribute to uv and never get a chance of fixing internally.

There is an argument to be made that for the case in astral-sh/uv#18316, since the range we get back covers the entire memory map, we could just accept it. It would fill the memory map and our reads can just return from this memory map with no further requests.

Our first request is from the end of the file, so if we'd get the whole file, we'd still overflow, we'd need a different path for that. (Treating this response as a regular streaming response?)

@EliteTK
Copy link

EliteTK commented Mar 9, 2026

there's something really bad going on with the user's server and they get a severe performance degradation due to that, that they'd otherwise attribute to uv and never get a chance of fixing internally.

I get that, but also some of our users just won't be able to do anything about this, so they'd get warnings they have to ignore.

It seems like a difficult balance.

@konstin
Copy link
Member Author

konstin commented Mar 9, 2026

Tbh if you're using an index server that's so badly broken it advertises range requests but isn't capable of returning correct responses (not to mention PEP 658 support), causing a massive degradation of performance in uv, complaining about this seems appropriate; it's not hard to come by a server or reverse proxy that implements this correctly, and I find it almost more reasonable to straight up reject a registry that doesn't even clear this minimal bar - It could just not advertise range request support!

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.

Panic with invalid content length in range reader

2 participants