Skip to content

Commit 86868de

Browse files
authored
Reject JSON bodies with trailing chars (#3453)
1 parent 49c8fac commit 86868de

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

axum/src/json.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,16 @@ where
181181
}
182182
}
183183

184-
let deserializer = &mut serde_json::Deserializer::from_slice(bytes);
185-
186-
match serde_path_to_error::deserialize(deserializer) {
187-
Ok(value) => Ok(Self(value)),
188-
Err(err) => Err(make_rejection(err)),
189-
}
184+
let mut deserializer = serde_json::Deserializer::from_slice(bytes);
185+
186+
serde_path_to_error::deserialize(&mut deserializer)
187+
.map_err(make_rejection)
188+
.and_then(|value| {
189+
deserializer
190+
.end()
191+
.map(|()| Self(value))
192+
.map_err(|err| JsonSyntaxError::from_err(err).into())
193+
})
190194
}
191195
}
192196

@@ -303,6 +307,30 @@ mod tests {
303307
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
304308
}
305309

310+
#[crate::test]
311+
async fn extra_chars_after_valid_json_syntax() {
312+
#[derive(Debug, Deserialize)]
313+
struct Input {
314+
foo: String,
315+
}
316+
317+
let app = Router::new().route("/", post(|input: Json<Input>| async { input.0.foo }));
318+
319+
let client = TestClient::new(app);
320+
let res = client
321+
.post("/")
322+
.body(r#"{ "foo": "bar" } baz "#)
323+
.header("content-type", "application/json")
324+
.await;
325+
326+
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
327+
let body_text = res.text().await;
328+
assert_eq!(
329+
body_text,
330+
"Failed to parse the request body as JSON: trailing characters at line 1 column 18"
331+
);
332+
}
333+
306334
#[derive(Deserialize)]
307335
struct Foo {
308336
#[allow(dead_code)]

0 commit comments

Comments
 (0)