Skip to content

Commit a0692f9

Browse files
avandecremejplatte
authored andcommitted
Reject JSON bodies with trailing chars (#3453)
1 parent ae80850 commit a0692f9

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
@@ -189,12 +189,16 @@ where
189189
}
190190
}
191191

192-
let deserializer = &mut serde_json::Deserializer::from_slice(bytes);
193-
194-
match serde_path_to_error::deserialize(deserializer) {
195-
Ok(value) => Ok(Json(value)),
196-
Err(err) => Err(make_rejection(err)),
197-
}
192+
let mut deserializer = serde_json::Deserializer::from_slice(bytes);
193+
194+
serde_path_to_error::deserialize(&mut deserializer)
195+
.map_err(make_rejection)
196+
.and_then(|value| {
197+
deserializer
198+
.end()
199+
.map(|()| Self(value))
200+
.map_err(|err| JsonSyntaxError::from_err(err).into())
201+
})
198202
}
199203
}
200204

@@ -311,6 +315,30 @@ mod tests {
311315
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
312316
}
313317

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

0 commit comments

Comments
 (0)