diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp index 47c914ee84..8f044dd214 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -466,6 +466,7 @@ static ThrowCompletionOr encode([[maybe_unused]] JS::GlobalObject& globa static ThrowCompletionOr decode(JS::GlobalObject& global_object, const String& string, StringView reserved_set) { StringBuilder decoded_builder; + auto code_point_start_offset = 0u; auto expected_continuation_bytes = 0; for (size_t k = 0; k < string.length(); k++) { auto code_unit = string[k]; @@ -488,11 +489,13 @@ static ThrowCompletionOr decode(JS::GlobalObject& global_object, const S if (second_digit >= 16) return global_object.vm().throw_completion(global_object, ErrorType::URIMalformed); - char decoded_code_unit = (first_digit << 4) | second_digit; + u8 decoded_code_unit = (first_digit << 4) | second_digit; k += 2; if (expected_continuation_bytes > 0) { decoded_builder.append(decoded_code_unit); expected_continuation_bytes--; + if (expected_continuation_bytes == 0 && !Utf8View(decoded_builder.string_view().substring_view(code_point_start_offset)).validate()) + return global_object.vm().throw_completion(global_object, ErrorType::URIMalformed); continue; } @@ -504,13 +507,16 @@ static ThrowCompletionOr decode(JS::GlobalObject& global_object, const S continue; } - auto leading_ones = count_trailing_zeroes_safe(static_cast(~decoded_code_unit)) - 24; + auto leading_ones = count_leading_zeroes_safe(static_cast(~decoded_code_unit)); if (leading_ones == 1 || leading_ones > 4) return global_object.vm().throw_completion(global_object, ErrorType::URIMalformed); + code_point_start_offset = decoded_builder.length(); decoded_builder.append(decoded_code_unit); expected_continuation_bytes = leading_ones - 1; } + if (expected_continuation_bytes > 0) + return global_object.vm().throw_completion(global_object, ErrorType::URIMalformed); return decoded_builder.build(); }