Skip to content

Commit

Permalink
LibWeb: Avoid re-encoding response headers
Browse files Browse the repository at this point in the history
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 LadybirdBrowser#1893
  • Loading branch information
F3n67u committed Dec 13, 2024
1 parent c159619 commit 002ab62
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 4 deletions.
6 changes: 3 additions & 3 deletions Libraries/LibWeb/Fetch/Fetching/Fetching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down Expand Up @@ -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));
}

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

Expand Down
8 changes: 8 additions & 0 deletions Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions Libraries/LibWeb/Infra/Strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ 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 input’s code
// point length and whose bytes have the same values as the values of input’s 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);
Expand All @@ -160,6 +163,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 input’s length and whose code points have the same values as the values of input’s 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);
Expand Down
1 change: 1 addition & 0 deletions Tests/LibWeb/Text/expected/http-non-ascii-content-type.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Content-Type:text/html;test=ÿ;charset=gbk
PASS (didn't crash)
3 changes: 2 additions & 1 deletion Tests/LibWeb/Text/input/http-non-ascii-content-type.html
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 002ab62

Please sign in to comment.