From ee381753fa22b0d91eafff204c9b000e215e4a9d Mon Sep 17 00:00:00 2001 From: Feng Yu Date: Fri, 13 Dec 2024 16:48:38 -0800 Subject: [PATCH] LibWeb: Fix `is_valid_status_text` to handle UTF-8 correctly Replaced `all_of` with a loop iterating over `code_points()` to properly validate Unicode characters in UTF-8. This change fixed a WPT subtest which I also imported. --- Libraries/LibWeb/Fetch/Response.cpp | 14 ++-- .../api/response/response-init-001.any.txt | 14 ++++ .../api/response/response-init-001.any.html | 15 +++++ .../api/response/response-init-001.any.js | 64 +++++++++++++++++++ 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-init-001.any.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.js diff --git a/Libraries/LibWeb/Fetch/Response.cpp b/Libraries/LibWeb/Fetch/Response.cpp index 6d3c133621267..2852e2070bc53 100644 --- a/Libraries/LibWeb/Fetch/Response.cpp +++ b/Libraries/LibWeb/Fetch/Response.cpp @@ -85,15 +85,21 @@ GC::Ref Response::create(JS::Realm& realm, GC::Ref= 0x21 && c <= 0x7E) || (c >= 0x80 && c <= 0xFF); - }); + if (status_text.is_empty()) + return true; + + for (auto code_point : status_text.code_points()) { + if (code_point == '\t' || code_point == ' ' || (code_point >= 0x21 && code_point <= 0x7E) || (code_point >= 0x80 && code_point <= 0xFF)) + continue; + return false; + } + return true; } // https://fetch.spec.whatwg.org/#initialize-a-response diff --git a/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-init-001.any.txt b/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-init-001.any.txt new file mode 100644 index 0000000000000..2eee99c4ad4b9 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-init-001.any.txt @@ -0,0 +1,14 @@ +Harness status: OK + +Found 9 tests + +9 Pass +Pass Check default value for type attribute +Pass Check default value for url attribute +Pass Check default value for ok attribute +Pass Check default value for status attribute +Pass Check default value for statusText attribute +Pass Check default value for body attribute +Pass Check status init values and associated getter +Pass Check statusText init values and associated getter +Pass Test that Response.headers has the [SameObject] extended attribute \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.html b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.html new file mode 100644 index 0000000000000..25792d9897635 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.html @@ -0,0 +1,15 @@ + + +Response init: simple cases + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.js b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.js new file mode 100644 index 0000000000000..559e49ad11ffe --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-init-001.any.js @@ -0,0 +1,64 @@ +// META: global=window,worker +// META: title=Response init: simple cases + +var defaultValues = { "type" : "default", + "url" : "", + "ok" : true, + "status" : 200, + "statusText" : "", + "body" : null +}; + +var statusCodes = { "givenValues" : [200, 300, 400, 500, 599], + "expectedValues" : [200, 300, 400, 500, 599] +}; +var statusTexts = { "givenValues" : ["", "OK", "with space", String.fromCharCode(0x80)], + "expectedValues" : ["", "OK", "with space", String.fromCharCode(0x80)] +}; +var initValuesDict = { "status" : statusCodes, + "statusText" : statusTexts +}; + +function isOkStatus(status) { + return 200 <= status && 299 >= status; +} + +var response = new Response(); +for (var attributeName in defaultValues) { + test(function() { + var expectedValue = defaultValues[attributeName]; + assert_equals(response[attributeName], expectedValue, + "Expect default response." + attributeName + " is " + expectedValue); + }, "Check default value for " + attributeName + " attribute"); +} + +for (var attributeName in initValuesDict) { + test(function() { + var valuesToTest = initValuesDict[attributeName]; + for (var valueIdx in valuesToTest["givenValues"]) { + var givenValue = valuesToTest["givenValues"][valueIdx]; + var expectedValue = valuesToTest["expectedValues"][valueIdx]; + var responseInit = {}; + responseInit[attributeName] = givenValue; + var response = new Response("", responseInit); + assert_equals(response[attributeName], expectedValue, + "Expect response." + attributeName + " is " + expectedValue + + " when initialized with " + givenValue); + assert_equals(response.ok, isOkStatus(response.status), + "Expect response.ok is " + isOkStatus(response.status)); + } + }, "Check " + attributeName + " init values and associated getter"); +} + +test(function() { + const response1 = new Response(""); + assert_equals(response1.headers, response1.headers); + + const response2 = new Response("", {"headers": {"X-Foo": "bar"}}); + assert_equals(response2.headers, response2.headers); + const headers = response2.headers; + response2.headers.set("X-Foo", "quux"); + assert_equals(headers, response2.headers); + headers.set("X-Other-Header", "baz"); + assert_equals(headers, response2.headers); +}, "Test that Response.headers has the [SameObject] extended attribute");