fix(highlight): ReDoS 检测降级为编辑器提示(实测漏判,不可作拒绝闸门)
上一提交把 isReDoSProne 当作 compileRules 的拒绝闸门,声称"9/9 危险全抓"。
独立复查证伪了这个结论:
## 实测漏判 —— 危险规则仍会进热路径
| pattern | 静态检测 | 实测 |
|---|---|---|
| [(](a+)+$ | 放行 | 30 字符 4065ms |
| (?:a\|a)+$ | 放行 | 26 字符 7547ms |
| ((a\|a))+$ | 放行 | 24 字符 16212ms |
| (\w\|\d)+$ | 放行 | 26 字符 14451ms |
根因三条:外层扫描不跟踪字符类状态([(] 里的 ( 被当组起始)、遇到不闭合
组时 return false 让整个函数交白卷、分支比较只做字面相等抓不到语义重叠。
## 实测误判 —— 合法规则被拒
(?:a{2,3})+ 等把 {n,m} 范围重复当成 {n} 固定重复。
尝试修复后每修一处引入新问题(补字符类状态后又误杀 (?:\d{2})+ 与 ipv4
预设),证明手写正则语法扫描有本质缺陷。
## 三个替代方案均否决(有实测依据)
1. 运行时熔断(循环内查时钟):**原理上无效**。单次 exec 阻塞 28426ms,
时钟检查根本执行不到
2. re2:不支持 lookbehind,perm/okstate/http 三条预设依赖它
3. Worker + 超时:**可靠**(6/6 危险全抓、806ms 内 tick 51 次主线程未阻塞)
但往返 0.11ms/块 vs 直接 0.035ms,且终端高亮必须同步(WriteBatcher 消费
同步染色结果)——只适合规则的异步校验,不适合热路径
## 本次改动
- compileRules 不再因 isReDoSProne 跳过规则:拒绝闸门会静默禁用合法规则
(已证实会误杀)却仍放进危险规则(已证实会漏判),两头都不对
- isReDoSProne 保留给编辑器提示:漏判不比改动前差,误判只是多一个警告而非
禁用功能
- 注释与 AGENTS.md 如实标注"只有提示没有根治",并记录三个方案的否决理由,
避免后来者重复踩坑
热路径的实际边界仍是 MAX_LINE_LEN(>4KB 行不进用户正则)+ MAX_PER_RULE。
真正的解法(Worker 异步校验 + 存盘前把关)列为未完成项。
This commit is contained in:
1 parent
c6aca15134
commit
68fa46b2e3
4 files changed
+66
-29
No files matched your search
@@ -179,3 +179,33 @@
|
||||
- i18n 新文案四语齐备(zh-CN/zh-TW/en/ja,缺译回退简体)
|
||||
- 渲染层新依赖一律 devDependencies;`@xterm/*` 版本必须与锁定的 6.1.0-beta.304 体系兼容,改依赖后必须真实 `npm install` 并跑 `node scripts/verify-deps.cjs`
|
||||
- 改动若触碰 AGENTS.md 已记载的行为,同步更新 AGENTS.md
|
||||
|
||||
## 最终 review 结论(2026-10-17 收尾)
|
||||
|
||||
对 `c6aca15` 做了独立复查,**发现 ReDoS 静态检测不可靠,已从「拒绝闸门」降级为「编辑器提示」**。
|
||||
|
||||
### 实测漏判(危险规则仍会进热路径)
|
||||
| pattern | 静态检测 | 实测耗时 |
|
||||
|---|---|---|
|
||||
| `[(](a+)+$` | 放行 | 30 字符 **4065ms** |
|
||||
| `(?:a|a)+$` | 放行 | 26 字符 **7547ms** |
|
||||
| `((a|a))+$` | 放行 | 24 字符 **16212ms** |
|
||||
| `(\w|\d)+$` | 放行 | 26 字符 **14451ms** |
|
||||
|
||||
根因:外层扫描不跟踪字符类状态(`[(` 里的 `(` 被当组起始)、遇到不闭合组时整个函数提前返回、分支比较只做字面相等。
|
||||
|
||||
### 实测误判(合法规则被拒)
|
||||
`(?:a{2,3})+`、`(?:\d{2})+` —— 把 `{n,m}` 范围重复当成 `{n}` 固定重复。
|
||||
|
||||
### 尝试修复但失败
|
||||
补字符类状态后又误杀 `(?:\d{2})+` 与 `ipv4` 预设。**每修一处引入新问题**,证明手写正则语法扫描有本质缺陷。
|
||||
|
||||
### 否决的三个替代方案
|
||||
1. **运行时熔断**(循环里查时钟):**原理上无效**。实测单次 `exec` 阻塞 **28426ms**,时钟检查根本执行不到
|
||||
2. **re2**:不支持 lookbehind,`perm`/`okstate`/`http` 三条预设依赖它
|
||||
3. **Worker + 超时**:**可靠**(6/6 危险全抓、主线程 806ms 内 tick 51 次未阻塞),但往返 0.11ms/块 vs 直接 0.035ms。**只适合规则异步校验,不适合热路径**
|
||||
|
||||
### 当前状态与遗留
|
||||
`isReDoSProne` 保留为**编辑器提示**(漏判不比改动前差,误判只是多一个警告而非禁用规则)。热路径边界仍是 `MAX_LINE_LEN`(>4KB 行不进用户正则)+ `MAX_PER_RULE`。
|
||||
|
||||
**未完成**:真正解法是 Worker 异步校验 + 规则存盘前把关。工作量中等,需单独排期。
|
||||
Reference in new issue
Block a user