Fix recursive call leading to stack overflow when tracing level filter is TRACE (#3312)

This commit is contained in:
Denis
2025-04-24 13:03:50 +02:00
committed by GitHub
parent 1599569df2
commit 6bf1fcbb29
3 changed files with 45 additions and 3 deletions
Generated
+1
View File
@@ -407,6 +407,7 @@ dependencies = [
"tower-layer",
"tower-service",
"tracing",
"tracing-subscriber",
"typed-json",
]
+2 -1
View File
@@ -38,7 +38,7 @@ multipart = ["dep:multer", "dep:fastrand"]
protobuf = ["dep:prost"]
scheme = []
query = ["dep:form_urlencoded", "dep:serde_html_form", "dep:serde_path_to_error"]
tracing = ["axum-core/tracing", "axum/tracing"]
tracing = ["axum-core/tracing", "axum/tracing", "dep:tracing"]
typed-header = ["dep:headers"]
typed-routing = ["dep:axum-macros", "dep:percent-encoding", "dep:serde_html_form", "dep:form_urlencoded"]
@@ -92,6 +92,7 @@ serde_json = "1.0.71"
tokio = { version = "1.14", features = ["full"] }
tower = { version = "0.5.2", features = ["util"] }
tower-http = { version = "0.6.0", features = ["map-response-body", "timeout"] }
tracing-subscriber = "0.3.19"
[lints]
workspace = true
+42 -2
View File
@@ -243,12 +243,13 @@ impl MultipartError {
/// Get the response body text used for this rejection.
pub fn body_text(&self) -> String {
let body = self.source.to_string();
axum_core::__log_rejection!(
rejection_type = Self,
body_text = self.body_text(),
body_text = body,
status = self.status(),
);
self.source.to_string()
body
}
/// Get the status code used for this rejection.
@@ -398,4 +399,43 @@ mod tests {
let res = client.post("/").multipart(form).await;
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
}
#[tokio::test]
#[cfg(feature = "tracing")]
async fn body_too_large_with_tracing() {
const BYTES: &[u8] = "<!doctype html><title>🦀</title>".as_bytes();
async fn handle(mut multipart: Multipart) -> impl IntoResponse {
let result: Result<(), MultipartError> = async {
while let Some(field) = multipart.next_field().await? {
field.bytes().await?;
}
Ok(())
}
.await;
let subscriber = tracing_subscriber::FmtSubscriber::builder()
.with_max_level(tracing::level_filters::LevelFilter::TRACE)
.with_writer(std::io::sink)
.finish();
let guard = tracing::subscriber::set_default(subscriber);
let response = result.into_response();
drop(guard);
response
}
let app = Router::new()
.route("/", post(handle))
.layer(DefaultBodyLimit::max(BYTES.len() - 1));
let client = TestClient::new(app);
let form =
reqwest::multipart::Form::new().part("file", reqwest::multipart::Part::bytes(BYTES));
let res = client.post("/").multipart(form).await;
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
}
}