LibWeb: Avoid re-encoding response headers

isomorphic encoding a value that has already been encoded will
result in garbage data. `response_headers` is already encoded in
ISO-8859-1/latin1, we cannot use `from_string_pair`, as it triggers
ISO-8859-1/latin1 encoding.

Follow-up of https://github.com/LadybirdBrowser/ladybird/pull/1893
This commit is contained in:
Feng Yu 2024-12-12 10:26:41 -08:00 committed by Jelle Raaijmakers
parent 3063be11a9
commit e0c0668f3d
Notes: github-actions[bot] 2024-12-17 12:45:04 +00:00
6 changed files with 22 additions and 7 deletions

View file

@ -2330,7 +2330,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> nonstandard_resource_loader_file_o
}
for (auto const& [name, value] : response_headers.headers()) {
auto header = Infrastructure::Header::from_string_pair(name, value);
auto header = Infrastructure::Header::from_latin1_pair(name, value);
response->header_list()->append(move(header));
}
@ -2396,7 +2396,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> nonstandard_resource_loader_file_o
response->set_status(status_code.value_or(200));
response->set_body(move(body));
for (auto const& [name, value] : response_headers.headers()) {
auto header = Infrastructure::Header::from_string_pair(name, value);
auto header = Infrastructure::Header::from_latin1_pair(name, value);
response->header_list()->append(move(header));
}
@ -2421,7 +2421,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> nonstandard_resource_loader_file_o
auto [body, _] = TRY_OR_IGNORE(extract_body(realm, data));
response->set_body(move(body));
for (auto const& [name, value] : response_headers.headers()) {
auto header = Infrastructure::Header::from_string_pair(name, value);
auto header = Infrastructure::Header::from_latin1_pair(name, value);
response->header_list()->append(move(header));
}

View file

@ -58,6 +58,14 @@ Header Header::from_string_pair(StringView name, StringView value)
};
}
Header Header::from_latin1_pair(StringView name, StringView value)
{
return Header {
.name = MUST(ByteBuffer::copy(name.bytes())),
.value = MUST(ByteBuffer::copy(value.bytes())),
};
}
GC::Ref<HeaderList> HeaderList::create(JS::VM& vm)
{
return vm.heap().allocate<HeaderList>();

View file

@ -29,6 +29,7 @@ struct Header {
[[nodiscard]] static Header copy(Header const&);
[[nodiscard]] static Header from_string_pair(StringView, StringView);
[[nodiscard]] static Header from_latin1_pair(StringView, StringView);
};
// https://fetch.spec.whatwg.org/#concept-header-list

View file

@ -147,11 +147,12 @@ ErrorOr<String> to_ascii_uppercase(StringView string)
// https://infra.spec.whatwg.org/#isomorphic-encode
ByteBuffer isomorphic_encode(StringView input)
{
// To isomorphic encode an isomorphic string input: return a byte sequence whose length is equal to inputs code
// point length and whose bytes have the same values as the values of inputs code points, in the same order.
// NOTE: This is essentially spec-speak for "Encode as ISO-8859-1 / Latin-1".
ByteBuffer buf = {};
for (auto code_point : Utf8View { input }) {
// VERIFY(code_point <= 0xFF);
if (code_point > 0xFF)
dbgln("FIXME: Trying to isomorphic encode a string with code points > U+00FF.");
VERIFY(code_point <= 0xFF);
buf.append((u8)code_point);
}
return buf;
@ -160,6 +161,9 @@ ByteBuffer isomorphic_encode(StringView input)
// https://infra.spec.whatwg.org/#isomorphic-decode
String isomorphic_decode(ReadonlyBytes input)
{
// To isomorphic decode a byte sequence input, return a string whose code point length is equal
// to inputs length and whose code points have the same values as the values of inputs bytes, in the same order.
// NOTE: This is essentially spec-speak for "Decode as ISO-8859-1 / Latin-1".
StringBuilder builder(input.size());
for (u8 code_point : input) {
builder.append_code_point(code_point);

View file

@ -1 +1,2 @@
Content-Type:text/html;test=ÿ;charset=gbk
PASS (didn't crash)

View file

@ -12,7 +12,8 @@
},
});
const blob = await fetch(url).then((response) => response.blob());
const headers = await fetch(url).then((response) => response.headers);
println("Content-Type:" + headers.get("Content-Type"));
println("PASS (didn't crash)");
} catch (err) {
println("FAIL - " + err);