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.
This commit is contained in:
Timothy Flynn 2026-04-28 14:32:57 -04:00 committed by Shannon Booth
parent d48db4e881
commit 8664eac047
3 changed files with 26 additions and 3 deletions

View file

@ -40,7 +40,7 @@ ErrorOr<JsonValue> JsonParser::parse(StringView input)
// │ │
// ╰─── u[0-9A-Za-z]{4} ──╯
//
ErrorOr<ByteString> JsonParser::consume_and_unescape_string()
ErrorOr<String> JsonParser::consume_and_unescape_string()
{
if (!consume_specific('"'))
return Error::from_string_literal("JsonParser: Expected '\"'");
@ -135,7 +135,7 @@ ErrorOr<ByteString> JsonParser::consume_and_unescape_string()
}
}
return final_sb.to_byte_string();
return final_sb.to_string();
}
ErrorOr<JsonValue> JsonParser::parse_object()

View file

@ -24,7 +24,7 @@ private:
ErrorOr<JsonValue> parse_json();
ErrorOr<JsonValue> parse_helper();
ErrorOr<ByteString> consume_and_unescape_string();
ErrorOr<String> consume_and_unescape_string();
ErrorOr<JsonValue> parse_array();
ErrorOr<JsonValue> parse_object();
ErrorOr<JsonValue> parse_number();

View file

@ -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());
}