From 28c89db3dff4510cd948c142e8ca0220f1a618dd Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 20 Mar 2026 13:03:07 +0100 Subject: [PATCH 1/4] add failing tests --- packages/tailwindcss/src/index.test.ts | 9 +++++++++ packages/tailwindcss/src/utils/escape.test.ts | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index 5eb7407d81dd..dd545601757d 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -1501,6 +1501,15 @@ describe('Parsing theme values from CSS', () => { `) }) + // https://github.com/tailwindlabs/tailwindcss/issues/19786 + test('out-of-range escaped CSS variable candidates do not crash the build', async () => { + expect(() => + run([ + String.raw`--Coding-Projects-CharacterMapper-Master-Workspace\d8819554-4725-4235-9d22-2d0ed572e924`, + ]), + ).not.toThrow() + }) + test('`@keyframes` in `@theme` are hoisted', async () => { expect( await compileCss( diff --git a/packages/tailwindcss/src/utils/escape.test.ts b/packages/tailwindcss/src/utils/escape.test.ts index ff7715b9d8dc..f4c8e1192862 100644 --- a/packages/tailwindcss/src/utils/escape.test.ts +++ b/packages/tailwindcss/src/utils/escape.test.ts @@ -11,4 +11,14 @@ describe('unescape', () => { test('removes backslashes', () => { expect(unescape(String.raw`red-1\/2`)).toMatchInlineSnapshot(`"red-1/2"`) }) + + test('replaces out-of-range escaped code points', () => { + expect( + unescape( + String.raw`--Coding-Projects-CharacterMapper-Master-Workspace\d8819554-4725-4235-9d22-2d0ed572e924`, + ), + ).toMatchInlineSnapshot( + `"--Coding-Projects-CharacterMapper-Master-Workspace�54-4725-4235-9d22-2d0ed572e924"`, + ) + }) }) From 01221c7b3b6a00ef971904c52806d8e3cc5170f9 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 20 Mar 2026 13:03:18 +0100 Subject: [PATCH 2/4] fix invalid codepoints during escape --- packages/tailwindcss/src/utils/escape.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/tailwindcss/src/utils/escape.ts b/packages/tailwindcss/src/utils/escape.ts index cbcfa62a0b42..c430e4ad42bf 100644 --- a/packages/tailwindcss/src/utils/escape.ts +++ b/packages/tailwindcss/src/utils/escape.ts @@ -74,8 +74,24 @@ export function escape(value: string) { export function unescape(escaped: string) { return escaped.replace(/\\([\dA-Fa-f]{1,6}[\t\n\f\r ]?|[\S\s])/g, (match) => { - return match.length > 2 - ? String.fromCodePoint(Number.parseInt(match.slice(1).trim(), 16)) - : match[1] + if (match.length <= 2) { + return match[1] + } + + let codePoint = Number.parseInt(match.slice(1).trim(), 16) + + if ( + // Invalid codepoint: https://infra.spec.whatwg.org/#code-point + codePoint === 0x0000 || + codePoint > 0x10ffff || + // Is surrogate: https://infra.spec.whatwg.org/#leading-surrogate + // - A leading surrogate is a code point that is in the range U+D800 to U+DBFF, inclusive. + // - A trailing surrogate is a code point that is in the range U+DC00 to U+DFFF, inclusive. + (codePoint >= 0xd800 && codePoint <= 0xdfff) + ) { + return '\uFFFD' + } + + return String.fromCodePoint(codePoint) }) } From 9a1e10c1c2174388531f591120139f16144bdb95 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 20 Mar 2026 14:34:37 +0100 Subject: [PATCH 3/4] simplify test --- packages/tailwindcss/src/index.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index dd545601757d..bf1c72c42178 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -1503,11 +1503,10 @@ describe('Parsing theme values from CSS', () => { // https://github.com/tailwindlabs/tailwindcss/issues/19786 test('out-of-range escaped CSS variable candidates do not crash the build', async () => { - expect(() => - run([ - String.raw`--Coding-Projects-CharacterMapper-Master-Workspace\d8819554-4725-4235-9d22-2d0ed572e924`, - ]), - ).not.toThrow() + // Shouldn't crash + await run([ + String.raw`--Coding-Projects-CharacterMapper-Master-Workspace\d8819554-4725-4235-9d22-2d0ed572e924`, + ]) }) test('`@keyframes` in `@theme` are hoisted', async () => { From d7394aff361bf7320213c582891a4bfe4cf155b1 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 20 Mar 2026 14:35:01 +0100 Subject: [PATCH 4/4] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b639aed9009..39e89832bf42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Improve canonicalizations for `tracking-*` utilities ([#19827](https://github.com/tailwindlabs/tailwindcss/pull/19827)) +- Fix crash due to invalid characters in candidate ([#19829](https://github.com/tailwindlabs/tailwindcss/pull/19829)) ## [4.2.2] - 2026-03-18