From ba1189cd1c47ab0593e0c3d7eee85e7aafc3462d Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 18 Sep 2024 12:10:47 -0400 Subject: [PATCH] LibWeb: Support cookie Max-Age attributes that exceed i64 limits Attributes have a max value length of 1024. So we theoretically need to support values in the range -${"9".repeat(1023)} to ${"9".repeat(1024)}. These obviously do not fit in an i64, so we were previously failing to parse the attribute. We will now cap the parsed value to the numeric limits of an i64, after ensuring that the attribute value is indeed a number. --- Tests/LibWeb/Text/expected/cookie.txt | 6 +++--- Tests/LibWeb/Text/input/cookie.html | 7 +++++-- Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp | 14 ++++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Tests/LibWeb/Text/expected/cookie.txt b/Tests/LibWeb/Text/expected/cookie.txt index f21cf9d5923..44c8a5ab8b2 100644 --- a/Tests/LibWeb/Text/expected/cookie.txt +++ b/Tests/LibWeb/Text/expected/cookie.txt @@ -14,9 +14,9 @@ Public suffix: "" SameSite=Lax: "cookie=value" SameSite=Strict: "cookie=value" SameSite=None: "" -Max-Age (before expiration): "cookie-max-age=value" -Expires (before expiration): "cookie-expires=value; cookie-max-age=value" -Max-Age (after expiration): "" +Max-Age (before expiration): "cookie-max-age1=value; cookie-max-age2=value" +Expires (before expiration): "cookie-expires=value; cookie-max-age1=value; cookie-max-age2=value" +Max-Age (after expiration): "cookie-max-age2=value" Expires (after expiration): "" Max-Age in past: "" Expires in past: "" diff --git a/Tests/LibWeb/Text/input/cookie.html b/Tests/LibWeb/Text/input/cookie.html index 4087d1d4c99..fc65d5547aa 100644 --- a/Tests/LibWeb/Text/input/cookie.html +++ b/Tests/LibWeb/Text/input/cookie.html @@ -113,16 +113,19 @@ }; const maxAgeTest1 = () => { - document.cookie = "cookie-max-age=value; max-age=1"; + document.cookie = "cookie-max-age1=value; max-age=1"; + document.cookie = `cookie-max-age2=value; max-age=${"1".repeat(1024)}`; printCookies("Max-Age (before expiration)"); }; const maxAgeTest2 = () => { printCookies("Max-Age (after expiration)"); + deleteCookie("cookie-max-age2"); }; const maxAgeInPastTest = () => { - document.cookie = "cookie=value; max-age=-1"; + document.cookie = "cookie1=value; max-age=-1"; + document.cookie = `cookie2=value; max-age=-${"1".repeat(1023)}`; printCookies("Max-Age in past"); }; diff --git a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp index d34fcb605fc..09c28ab0b2f 100644 --- a/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp +++ b/Userland/Libraries/LibWeb/Cookie/ParsedCookie.cpp @@ -226,14 +226,20 @@ void on_max_age_attribute(ParsedCookie& parsed_cookie, StringView attribute_valu // 2. If the first character of the attribute-value is neither a DIGIT, nor a "-" character followed by a DIGIT, // ignore the cookie-av. - if (!is_ascii_digit(attribute_value[0]) && attribute_value[0] != '-') + // 3. If the remainder of attribute-value contains a non-DIGIT character, ignore the cookie-av. + auto digits = attribute_value[0] == '-' ? attribute_value.substring_view(1) : attribute_value; + + if (digits.is_empty() || !all_of(digits, is_ascii_digit)) return; - // 3. If the remainder of attribute-value contains a non-DIGIT character, ignore the cookie-av. // 4. Let delta-seconds be the attribute-value converted to a base 10 integer. auto delta_seconds = attribute_value.to_number(); - if (!delta_seconds.has_value()) - return; + if (!delta_seconds.has_value()) { + // We know the attribute value only contains digits, so if we failed to parse, it is because the result did not + // fit in an i64. Set the value to the i64 limits in that case. The positive limit will be further capped below, + // and the negative limit will be immediately expired in the cookie jar. + delta_seconds = attribute_value[0] == '-' ? NumericLimits::min() : NumericLimits::max(); + } // 5. Let cookie-age-limit be the maximum age of the cookie (which SHOULD be 400 days or less, see Section 5.5). auto cookie_age_limit = maximum_cookie_age();