From a581197a274d96d29d7c5a8989410acb53320029 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 27 Sep 2026 20:11:00 +0200 Subject: [PATCH] FakeProfileThemes: fix crashes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is quite a weird one. The old regex was causing issues for some users and even Stack overflow errors while trying to parse the Regex?? Explanation from Claude: The character classes here (\u{e0061}-\u{e0066}, \u{e0041}-\u{e0046}, \u{e0030}-\u{e0039}) are all in the Unicode Tags block (U+E0000–U+E007F), which is outside the Basic Multilingual Plane — every one of these code points is represented internally as a surrogate pair. When you build a /u-flag regex with several ranges of astral (non-BMP) code points inside a character class, and then apply a repetition quantifier to that class ({1,6}, or +? as in the actual error), V8's Irregexp compiler has to expand/canonicalize the class and unroll the quantifier. For BMP regexes this is cheap, but the astral-range handling triggers a much deeper recursive expansion in the compiler itself. This is a known class of V8/Chromium bugs (regex-compiler stack overflow on Unicode-mode patterns with supplementary-plane character-class ranges + quantifiers) — it's not something wrong with your logic, it's the compiling of the pattern that blows the native stack on affected Chromium versions/builds, not the matching. That's why it only hits "some users": it depends on their exact V8 build/stack size, not the input string. --- src/plugins/fakeProfileThemes/index.tsx | 28 +++++++++++-------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index b1a284deb..1d462491c 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -51,26 +51,22 @@ function encode(primary: number, accent: number): string { return (padding || "") + " " + encoded; } -// Courtesy of Cynthia. +const DecodeRegex = /\[#([a-fA-F0-9]{1,6}),#([a-fA-F0-9]{1,6})\]/; function decode(bio: string): Array | null { if (bio == null) return null; - const colorString = bio.match( - /\u{e005b}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{1,6})\u{e002c}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{1,6})\u{e005d}/u, - ); - if (colorString != null) { - const parsed = [...colorString[0]] - .map(x => String.fromCodePoint(x.codePointAt(0)! - 0xe0000)) - .join(""); - const colors = parsed - .substring(1, parsed.length - 1) - .split(",") - .map(x => parseInt(x.replace("#", "0x"), 16)); - - return colors; - } else { - return null; + let ascii = ""; + for (const ch of bio) { + const cp = ch.codePointAt(0)!; + if (cp >= 0xe0000 && cp <= 0xe007f) { + ascii += String.fromCodePoint(cp - 0xe0000); + } } + + const match = ascii.match(DecodeRegex); + if (!match) return null; + + return [parseInt(match[1], 16), parseInt(match[2], 16)]; } const settings = definePluginSettings({