FakeProfileThemes: fix crashes

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.
This commit is contained in:
Vendicated 2026-09-27 20:11:00 +02:00
parent 799eeba828
commit a581197a27
No known key found for this signature in database
GPG key ID: D66986BAF75ECF18

View file

@ -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<number> | 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({