From 7afac71824107811e15ed1138d3adc20dd5d9e3e Mon Sep 17 00:00:00 2001 From: xxiaoxiong Date: Thu, 28 May 2026 09:18:16 +0800 Subject: [PATCH 1/2] fix(javascript): prevent XML_TAG from matching TypeScript type assertion with array syntax When TypeScript uses angle bracket type assertions with array syntax (e.g. `value`), the XML_TAG pattern in JavaScript grammar was incorrectly matching `` - nextChar === "," + nextChar === "," || + // the [ gives away that this is a type assertion, not HTML + // `` in TypeScript type assertions + nextChar === "[" ) { response.ignoreMatch(); return; From ef4f60ac0cfdb6a2450dd3317877f60210269675 Mon Sep 17 00:00:00 2001 From: xxiaoxiong Date: Fri, 29 May 2026 01:26:32 +0800 Subject: [PATCH 2/2] fix(c,cpp): quadratic ReDoS in FUNCTION_DECLARATION regex The begin pattern '(' + FUNCTION_TYPE_RE + '[\*&\s]+)+' + FUNCTION_TITLE contains a nested quantifier: the outer + wraps a group that itself contains [\*&\s]+. When applied to input without a matching function title (e.g. repeated words separated by spaces), the regex engine tries all possible ways to partition whitespace between inner and outer groups, resulting in O(n^2) backtracking. Fix by restructuring the pattern to avoid nested quantifiers: (' + FUNCTION_TYPE_RE + '\s*[\*&]+\s*)*(?:' + FUNCTION_TYPE_RE + '\s*[\*&]*\s*)?' + FUNCTION_TITLE The outer + is split into an outer * (repeating type+modifier pairs) and a final optional type pair, with whitespace and pointer/reference operators matched separately in each group rather than in a single overlapping character class. This eliminates the quadratic backtracking while preserving the original matching semantics. Fixes #4362 Affects: C (c.js) and C++ (cpp.js), inherited by Arduino. --- src/languages/c.js | 2 +- src/languages/cpp.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/c.js b/src/languages/c.js index 4c502d91c6..114339b831 100644 --- a/src/languages/c.js +++ b/src/languages/c.js @@ -234,7 +234,7 @@ export default function(hljs) { }; const FUNCTION_DECLARATION = { - begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE, + begin: '(' + FUNCTION_TYPE_RE + '\\s*[\\*&]+\\s*)*(?:' + FUNCTION_TYPE_RE + '\\s*[\\*&]*\\s*)?' + FUNCTION_TITLE, returnBegin: true, end: /[{;=]/, excludeEnd: true, diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 1b3e337784..9f75808d5a 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -473,7 +473,7 @@ export default function(hljs) { const FUNCTION_DECLARATION = { className: 'function', - begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE, + begin: '(' + FUNCTION_TYPE_RE + '\\s*[\\*&]+\\s*)*(?:' + FUNCTION_TYPE_RE + '\\s*[\\*&]*\\s*)?' + FUNCTION_TITLE, returnBegin: true, end: /[{;=]/, excludeEnd: true,