From 9c243caac4c3c77921af537cddd317d1f6c2c6da Mon Sep 17 00:00:00 2001 From: Feng Yu Date: Tue, 10 Dec 2024 10:53:02 -0800 Subject: [PATCH] LibWeb: Add statusText validation for Response constructor Implemented validation to ensure `statusText` matches the `reason-phrase` token production. This change fixes a WPT subtest which I have imported. --- Libraries/LibWeb/Fetch/Response.cpp | 16 ++++++++++- .../fetch/api/response/response-error.any.txt | 16 +++++++++++ .../api/response/response-error.any.html | 15 +++++++++++ .../fetch/api/response/response-error.any.js | 27 +++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-error.any.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.js diff --git a/Libraries/LibWeb/Fetch/Response.cpp b/Libraries/LibWeb/Fetch/Response.cpp index 3bb89a8f2e4c..6d3c13362126 100644 --- a/Libraries/LibWeb/Fetch/Response.cpp +++ b/Libraries/LibWeb/Fetch/Response.cpp @@ -84,6 +84,18 @@ GC::Ref Response::create(JS::Realm& realm, GC::Ref= 0x21 && c <= 0x7E) || (c >= 0x80 && c <= 0xFF); + }); +} + // https://fetch.spec.whatwg.org/#initialize-a-response WebIDL::ExceptionOr Response::initialize_response(ResponseInit const& init, Optional const& body) { @@ -91,7 +103,9 @@ WebIDL::ExceptionOr Response::initialize_response(ResponseInit const& init if (init.status < 200 || init.status > 599) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Status must be in range 200-599"sv }; - // FIXME: 2. If init["statusText"] does not match the reason-phrase token production, then throw a TypeError. + // 2. If init["statusText"] does not match the reason-phrase token production, then throw a TypeError. + if (!is_valid_status_text(init.status_text)) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid statusText: does not match the reason-phrase token production"sv }; // 3. Set response’s response’s status to init["status"]. m_response->set_status(init.status); diff --git a/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-error.any.txt b/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-error.any.txt new file mode 100644 index 000000000000..7b365758017d --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/fetch/api/response/response-error.any.txt @@ -0,0 +1,16 @@ +Harness status: OK + +Found 10 tests + +10 Pass +Pass Throws RangeError when responseInit's status is 0 +Pass Throws RangeError when responseInit's status is 100 +Pass Throws RangeError when responseInit's status is 199 +Pass Throws RangeError when responseInit's status is 600 +Pass Throws RangeError when responseInit's status is 1000 +Pass Throws TypeError when responseInit's statusText is + +Pass Throws TypeError when responseInit's statusText is Ā +Pass Throws TypeError when building a response with body and a body status of 204 +Pass Throws TypeError when building a response with body and a body status of 205 +Pass Throws TypeError when building a response with body and a body status of 304 \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.html b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.html new file mode 100644 index 000000000000..f7c4a6e53440 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.html @@ -0,0 +1,15 @@ + + +Response error + + + + +
+ diff --git a/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.js b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.js new file mode 100644 index 000000000000..a76bc4380286 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/fetch/api/response/response-error.any.js @@ -0,0 +1,27 @@ +// META: global=window,worker +// META: title=Response error + +var invalidStatus = [0, 100, 199, 600, 1000]; +invalidStatus.forEach(function(status) { + test(function() { + assert_throws_js(RangeError, function() { new Response("", { "status" : status }); }, + "Expect RangeError exception when status is " + status); + },"Throws RangeError when responseInit's status is " + status); +}); + +var invalidStatusText = ["\n", "Ā"]; +invalidStatusText.forEach(function(statusText) { + test(function() { + assert_throws_js(TypeError, function() { new Response("", { "statusText" : statusText }); }, + "Expect TypeError exception " + statusText); + },"Throws TypeError when responseInit's statusText is " + statusText); +}); + +var nullBodyStatus = [204, 205, 304]; +nullBodyStatus.forEach(function(status) { + test(function() { + assert_throws_js(TypeError, + function() { new Response("body", {"status" : status }); }, + "Expect TypeError exception "); + },"Throws TypeError when building a response with body and a body status of " + status); +});