mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-06 00:00:17 +02:00
Fix integer underflow in try_range_response for empty files (#3566)
This commit is contained in:
Generated
+8
-7
@@ -397,6 +397,7 @@ dependencies = [
|
|||||||
"serde_html_form",
|
"serde_html_form",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_path_to_error",
|
"serde_path_to_error",
|
||||||
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@@ -2947,9 +2948,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "listenfd"
|
name = "listenfd"
|
||||||
@@ -4139,9 +4140,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.42"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -4865,12 +4866,12 @@ checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.14.0"
|
version = "3.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
|
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"fastrand",
|
"fastrand",
|
||||||
|
"getrandom 0.3.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ hyper = "1.0.0"
|
|||||||
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] }
|
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] }
|
||||||
serde = { version = "1.0.221", features = ["derive"] }
|
serde = { version = "1.0.221", features = ["derive"] }
|
||||||
serde_json = "1.0.71"
|
serde_json = "1.0.71"
|
||||||
|
tempfile = "3.23.0"
|
||||||
tokio = { version = "1.14", features = ["full"] }
|
tokio = { version = "1.14", features = ["full"] }
|
||||||
tower = { version = "0.5.2", features = ["util"] }
|
tower = { version = "0.5.2", features = ["util"] }
|
||||||
tower-http = { version = "0.6.0", features = ["map-response-body", "timeout"] }
|
tower-http = { version = "0.6.0", features = ["map-response-body", "timeout"] }
|
||||||
|
|||||||
@@ -191,6 +191,10 @@ where
|
|||||||
let metadata = file.metadata().await?;
|
let metadata = file.metadata().await?;
|
||||||
let total_size = metadata.len();
|
let total_size = metadata.len();
|
||||||
|
|
||||||
|
if total_size == 0 {
|
||||||
|
return Ok((StatusCode::RANGE_NOT_SATISFIABLE, "Range Not Satisfiable").into_response());
|
||||||
|
}
|
||||||
|
|
||||||
if end == 0 {
|
if end == 0 {
|
||||||
end = total_size - 1;
|
end = total_size - 1;
|
||||||
}
|
}
|
||||||
@@ -596,4 +600,52 @@ mod tests {
|
|||||||
}
|
}
|
||||||
Some((start, end))
|
Some((start, end))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn response_range_empty_file() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let file = tempfile::NamedTempFile::new()?;
|
||||||
|
file.as_file().set_len(0)?;
|
||||||
|
let path = file.path().to_owned();
|
||||||
|
|
||||||
|
let app = Router::new().route(
|
||||||
|
"/range_empty",
|
||||||
|
get(move |headers: HeaderMap| {
|
||||||
|
let path = path.clone();
|
||||||
|
async move {
|
||||||
|
let range_header = headers
|
||||||
|
.get(header::RANGE)
|
||||||
|
.and_then(|value| value.to_str().ok());
|
||||||
|
|
||||||
|
let (start, end) = if let Some(range) = range_header {
|
||||||
|
if let Some(range) = parse_range_header(range) {
|
||||||
|
range
|
||||||
|
} else {
|
||||||
|
return (StatusCode::RANGE_NOT_SATISFIABLE, "Invalid Range")
|
||||||
|
.into_response();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
FileStream::<ReaderStream<File>>::try_range_response(path, start, end)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = app
|
||||||
|
.oneshot(
|
||||||
|
Request::builder()
|
||||||
|
.uri("/range_empty")
|
||||||
|
.header(header::RANGE, "bytes=0-")
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user