From 73f0d25405125afa0dba907b8c1fde1c19e8d410 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Wed, 28 Oct 2026 09:09:41 +0000 Subject: [PATCH] Reject signed numbers in Content-Range parsing Found while testing crates/fetch/src/lib.rs:465 (parse_content_range) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/fetch/src/lib.rs | 13 +++++++++++-- crates/fetch/src/tests.rs | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/fetch/src/lib.rs b/crates/fetch/src/lib.rs index 12daff541..07552e4bb 100644 --- a/crates/fetch/src/lib.rs +++ b/crates/fetch/src/lib.rs @@ -466,16 +466,25 @@ fn parse_content_range(v: &str) -> Option<(u64, Option)> { let v = v.trim().strip_prefix("bytes")?.trim(); let (range, total) = v.split_once('/')?; let (a, b) = range.split_once('-')?; - let (a, b) = (a.trim().parse::().ok()?, b.trim().parse::().ok()?); + let (a, b) = (digits(a)?, digits(b)?); if b < a { return None; } let total = match total.trim() { "*" => None, - t => Some(t.parse::().ok()?), + t => Some(digits(t)?), }; Some((a, total)) } +/// A non-empty run of ASCII digits as a `u64` (no sign, unlike `str::parse`). +fn digits(s: &str) -> Option { + let s = s.trim(); + if s.is_empty() || !s.bytes().all(|b| b.is_ascii_digit()) { + return None; + } + s.parse().ok() +} + #[cfg(test)] mod tests; diff --git a/crates/fetch/src/tests.rs b/crates/fetch/src/tests.rs index 08f869dcc..2a9c91f4f 100644 --- a/crates/fetch/src/tests.rs +++ b/crates/fetch/src/tests.rs @@ -335,6 +335,10 @@ fn content_ranges() { assert_eq!(parse_content_range("bytes 0-0/*"), Some((0, None))); assert_eq!(parse_content_range("bytes 9-1/300"), None); assert_eq!(parse_content_range("items 1-2/3"), None); + assert_eq!(parse_content_range("bytes +100-+299/+300"), None); + assert_eq!(parse_content_range("bytes 100-+299/300"), None); + assert_eq!(parse_content_range("bytes 100-299/+300"), None); + assert_eq!(parse_content_range("bytes 1-/3"), None); } /// A bearer token goes only to https, only to the host the download began at, and only when there is one.