From 5672433f16b2cfa119ca8fcb9129e4e040aeacdb Mon Sep 17 00:00:00 2001 From: lionel-rowe Date: Fri, 20 Sep 2024 11:20:05 +0800 Subject: [PATCH] fix(http): use non-locale-sensitive string methods for comparison --- http/_negotiation/encoding.ts | 2 +- http/cookie.ts | 2 +- http/cookie_test.ts | 34 ++++++++++++++++++++++++++++++++++ http/negotiation_test.ts | 31 +++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/http/_negotiation/encoding.ts b/http/_negotiation/encoding.ts index 243e6872b511..4fe39adc0d50 100644 --- a/http/_negotiation/encoding.ts +++ b/http/_negotiation/encoding.ts @@ -71,7 +71,7 @@ function specify( return; } let s = 0; - if (spec.encoding.toLocaleLowerCase() === encoding.toLocaleLowerCase()) { + if (spec.encoding.toLowerCase() === encoding.toLowerCase()) { s = 1; } else if (spec.encoding !== "*") { return; diff --git a/http/cookie.ts b/http/cookie.ts index c3afd705b491..9899a97b96a2 100644 --- a/http/cookie.ts +++ b/http/cookie.ts @@ -358,7 +358,7 @@ function parseSetCookie(value: string): Cookie | null { }; for (const [key, value] of attrs.slice(1)) { - switch (key.toLocaleLowerCase()) { + switch (key.toLowerCase()) { case "expires": cookie.expires = new Date(value); break; diff --git a/http/cookie_test.ts b/http/cookie_test.ts index c471e45a4de2..7c10acb6c3b5 100644 --- a/http/cookie_test.ts +++ b/http/cookie_test.ts @@ -1,4 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +import { stub } from "@std/testing/mock"; import { deleteCookie, getCookies, @@ -615,3 +616,36 @@ Deno.test({ assertEquals(getSetCookies(headers), []); }, }); + +Deno.test({ + name: "getSetCookies() is locale independent", + fn() { + const setCookie = "a=b; EXPIRES=Thu, 19 Sep 2024 07:47:28 GMT"; + const headers = new Headers({ "set-cookie": setCookie }); + const expected = [{ + "name": "a", + "value": "b", + "expires": new Date("2024-09-19T07:47:28.000Z"), + }]; + + assertEquals(getSetCookies(headers), expected); + + { + /** + * Use of locale-sensitive methods with undefined locale may cause + * environment-sensitive bugs - + * [issue](https://github.com/denoland/std/issues/6016) + */ + const toLocaleLowerCase = String.prototype.toLocaleLowerCase; + using _ = stub( + String.prototype, + "toLocaleLowerCase", + function (locale) { + return toLocaleLowerCase.call(this, locale ?? "tr-TR"); + }, + ); + + assertEquals(getSetCookies(headers), expected); + } + }, +}); diff --git a/http/negotiation_test.ts b/http/negotiation_test.ts index 82ee61d2bb0d..c8f9e88fdde2 100644 --- a/http/negotiation_test.ts +++ b/http/negotiation_test.ts @@ -2,6 +2,7 @@ import { assertEquals } from "@std/assert"; import { accepts, acceptsEncodings, acceptsLanguages } from "./negotiation.ts"; +import { stub } from "@std/testing/mock"; Deno.test({ name: "accepts() handles no args", @@ -109,6 +110,36 @@ Deno.test({ }, }); +Deno.test({ + name: "acceptsEncodings() is locale independent", + fn() { + const req = new Request("https://example.com/", { + headers: { "accept-encoding": "GZIP" }, + }); + const encoding = "gzip"; + + assertEquals(acceptsEncodings(req, encoding), encoding); + + { + /** + * Use of locale-sensitive methods with undefined locale may cause + * environment-sensitive bugs - + * [issue](https://github.com/denoland/std/issues/6016) + */ + const toLocaleLowerCase = String.prototype.toLocaleLowerCase; + using _ = stub( + String.prototype, + "toLocaleLowerCase", + function (locale) { + return toLocaleLowerCase.call(this, locale ?? "tr-TR"); + }, + ); + + assertEquals(acceptsEncodings(req, encoding), encoding); + } + }, +}); + Deno.test({ name: "acceptsLanguages() handles no args", fn() {