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.
This commit is contained in:
Feng Yu 2024-12-10 10:53:02 -08:00 committed by Andrew Kaster
parent 93a1c45eb2
commit 9c243caac4
Notes: github-actions[bot] 2024-12-11 23:35:08 +00:00
4 changed files with 73 additions and 1 deletions

View file

@ -84,6 +84,18 @@ GC::Ref<Response> Response::create(JS::Realm& realm, GC::Ref<Infrastructure::Res
return response_object;
}
// https://httpwg.org/specs/rfc9112.html#status.line
static bool is_valid_status_text(StringView status_text)
{
// A status text is a valid status text if it matches the reason-phrase token production.
// reason-phrase = 1*( HTAB / SP / VCHAR / obs-text )
// VCHAR = %x21-7E
// obs-text = %x80-FF
return all_of(status_text, [](auto c) {
return c == '\t' || c == ' ' || (c >= 0x21 && c <= 0x7E) || (c >= 0x80 && c <= 0xFF);
});
}
// https://fetch.spec.whatwg.org/#initialize-a-response
WebIDL::ExceptionOr<void> Response::initialize_response(ResponseInit const& init, Optional<Infrastructure::BodyWithType> const& body)
{
@ -91,7 +103,9 @@ WebIDL::ExceptionOr<void> 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 responses responses status to init["status"].
m_response->set_status(init.status);

View file

@ -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

View file

@ -0,0 +1,15 @@
<!doctype html>
<meta charset=utf-8>
<title>Response error</title>
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<div id=log></div>
<script src="../../../fetch/api/response/response-error.any.js"></script>

View file

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