From 8664eac047ef3336c39843666043a1571ac2475a Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 28 Apr 2026 14:32:57 -0400 Subject: [PATCH] AK: Protect AK's JSON parser against invalid UTF-8 We were forming parsed JSON strings as a ByteString and converting this to a String wrapped with a MUST. Let's instead create a String from the get-go and let the encoding error propagate. --- AK/JsonParser.cpp | 4 ++-- AK/JsonParser.h | 2 +- Tests/AK/TestJSON.cpp | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/AK/JsonParser.cpp b/AK/JsonParser.cpp index 71e41964ba..00c55364d2 100644 --- a/AK/JsonParser.cpp +++ b/AK/JsonParser.cpp @@ -40,7 +40,7 @@ ErrorOr JsonParser::parse(StringView input) // │ │ // ╰─── u[0-9A-Za-z]{4} ──╯ // -ErrorOr JsonParser::consume_and_unescape_string() +ErrorOr JsonParser::consume_and_unescape_string() { if (!consume_specific('"')) return Error::from_string_literal("JsonParser: Expected '\"'"); @@ -135,7 +135,7 @@ ErrorOr JsonParser::consume_and_unescape_string() } } - return final_sb.to_byte_string(); + return final_sb.to_string(); } ErrorOr JsonParser::parse_object() diff --git a/AK/JsonParser.h b/AK/JsonParser.h index d6d0ea1b18..9253f90591 100644 --- a/AK/JsonParser.h +++ b/AK/JsonParser.h @@ -24,7 +24,7 @@ private: ErrorOr parse_json(); ErrorOr parse_helper(); - ErrorOr consume_and_unescape_string(); + ErrorOr consume_and_unescape_string(); ErrorOr parse_array(); ErrorOr parse_object(); ErrorOr parse_number(); diff --git a/Tests/AK/TestJSON.cpp b/Tests/AK/TestJSON.cpp index 866321447b..aabfa44ebf 100644 --- a/Tests/AK/TestJSON.cpp +++ b/Tests/AK/TestJSON.cpp @@ -665,3 +665,26 @@ TEST_CASE(json_object_move_from_value) EXPECT_EQ(array2->at(0).as_bool(), false); EXPECT_EQ(array2->at(1).as_string(), "string"sv); } + +TEST_CASE(invalid_utf8) +{ + // Incomplete 2-byte sequence + EXPECT(JsonValue::from_string("{\"key\": \"value\xcf\"}"sv).is_error()); + EXPECT(JsonValue::from_string("{\"key\xcf\": \"value\"}"sv).is_error()); + + // Incomplete 3-byte sequence + EXPECT(JsonValue::from_string("{\"key\": \"value\xef\xbf\"}"sv).is_error()); + EXPECT(JsonValue::from_string("{\"key\xef\xbf\": \"value\"}"sv).is_error()); + + // Invalid start byte + EXPECT(JsonValue::from_string("{\"key\": \"value\xf8\"}"sv).is_error()); + EXPECT(JsonValue::from_string("{\"key\xf8\": \"value\"}"sv).is_error()); + + // Invalid continuation byte + EXPECT(JsonValue::from_string("{\"key\": \"value\xc3\x28\"}"sv).is_error()); + EXPECT(JsonValue::from_string("{\"key\xc3\x28\": \"value\"}"sv).is_error()); + + // Multiple invalid bytes + EXPECT(JsonValue::from_string("{\"key\": \"value\xff\xff\"}"sv).is_error()); + EXPECT(JsonValue::from_string("{\"key\xff\xff\": \"value\"}"sv).is_error()); +}