TokenReader subrange bounds enforced inconsistently: peekToken/peekPreviousTokenKind/backtrackToMarker ignore embedded window
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 72/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- typescript
- 领域
- compilers
调研方向
从 tsdoc/src/parser/TokenReader.ts 开始,将 peekToken()、peekPreviousTokenKind() 和 backtrackToMarker() 与受保护的同级方法进行比较。检查嵌入式 reader 的行为,以及 issue 中提到的 NodeParser 调用点。完成标准是:三个方法都遵守 [_readerStartIndex, _readerEndIndex) 窗口,并且通过测试覆盖所选择的输入结束行为。
由索引模型根据 Issue 内容生成。
描述
Summary
TokenReader respects its embedded subrange (_readerStartIndex/_readerEndIndex) in peekTokenKind()/peekTokenAfterKind()/peekTokenAfterAfterKind(), but three sibling methods ignore those bounds: peekToken() has no end guard at all, and peekPreviousTokenKind() / backtrackToMarker() compare against 0 / allow rewinding before the subrange start. This leaks outer tokens into embedded parses and can return undefined where Token is promised.
Location
- File:
tsdoc/src/parser/TokenReader.ts - Class:
TokenReader - Methods:
peekToken(): Token—return this.tokens[this._currentIndex];with no_readerEndIndexcheckpeekPreviousTokenKind()—if (this._currentIndex === 0)instead of=== this._readerStartIndexbacktrackToMarker(marker)— checksmarker > this._currentIndexbut notmarker < this._readerStartIndex
Contrast with the guarded siblings in the same file:
public peekTokenKind(): TokenKind {
if (this._currentIndex >= this._readerEndIndex) {
return TokenKind.EndOfInput;
}
...
}
Problem
peekToken()past end returnsundefined: return type claimsToken, but past_readerEndIndexthe index expression yieldsundefined. Callers doingpeekToken().range/peekToken().kindthen throwTypeError: Cannot read properties of undefinedinstead of getting a cleanEndOfInputsignal. Current internal hot paths inNodeParser.tshappen to callpeekTokenKind()first (e.g. block/inline tagbadCharacterpaths), which masks the hole, but the public API contract is broken for any external consumer or future internal use.peekPreviousTokenKind()leaks across embedded start: for an embedded reader starting at index N>0, calling it at the embedded start returnstokens[N-1].kind(outer context) instead ofEndOfInput.NodeParser._parseBlockTagand_parseFencedCodeswitch on this to decide start-of-input behavior (AtSignInWord,CodeFenceOpeningIndent); an embedded@or fence at the subrange start can therefore be misclassified using the token before the subrange.backtrackToMarker()can rewind before subrange start: nothing preventsmarker < _readerStartIndex, letting a laterreadToken()consume outer tokens that the embedded reader was explicitly scoped to exclude.
Trigger / Reproduction
Based on static analysis (no execution performed):
- Construct
new TokenReader(parserContext, embeddedSequence)whereembeddedSequence.startIndex > 0, advance to the embedded start, and callpeekPreviousTokenKind()— returns the outer predecessor kind instead ofEndOfInput. - Call
peekToken()when_currentIndex === _readerEndIndex— returnsundefinedinstead of signaling end (comparepeekTokenKind()returningEndOfInputin the same state). - Call
backtrackToMarker(outerMarker)withouterMarker < _readerStartIndexon an embedded reader — accepted, subsequent reads escape the subrange.
Note: this is a static-analysis finding; I did not execute a parser fixture.
Expected Behavior
All TokenReader accessors/mutators should honor the same [ _readerStartIndex, _readerEndIndex ) window: peekToken() should signal end (or throw a clear parser-bug error like readToken() does) instead of returning undefined; peekPreviousTokenKind() should return EndOfInput at the subrange start; backtrackToMarker() should reject markers below the subrange start.
Actual Behavior
Subrange bounds are enforced inconsistently, so embedded parses can observe outer tokens and end-of-input handling differs by method.
Impact
- Potential spurious
AtSignInWord/ fence-indent errors for embedded constructs starting at a subrange boundary. undefined-tokenTypeErrors for API consumers usingpeekToken()at end, bypassing the cleanEndOfInputprotocol every sibling method follows.
Suggested Direction
- Mirror the existing
peekTokenKind()guard inpeekToken()(return theEndOfInputtoken or throw a parser-bug error — maintainer's choice, but document it), change thepeekPreviousTokenKind()zero-check to_readerStartIndex, and add amarker < _readerStartIndexrejection inbacktrackToMarker(). No grammar changes needed.
Evidence
- Source via API:
tsdoc/src/parser/TokenReader.tsshows guardedpeekTokenKind/peekTokenAfterKind/peekTokenAfterAfterKindvs unguardedpeekToken/peekPreviousTokenKind/backtrackToMarker;tsdoc/src/parser/NodeParser.tsshowspeekPreviousTokenKindgatingAtSignInWord/CodeFenceOpeningIndentand embeddedTokenReaderconstruction for scoped parses. - Duplicate check: issue search for
peekToken TokenReader boundsreturnstotal_count: 0, and open issues contain no TokenReader-boundary report — no apparent duplicate. This is a non-security correctness finding, so Microsoft's private-security-disclosure requirement does not apply.
Classification
- FACT: three
TokenReadermethods ignore the subrange window that three sibling methods enforce (verified in source via API). - INFERENCE: embedded parses can observe out-of-range tokens; end-of-input
peekToken()yieldsundefined. - HYPOTHESIS: aligning all methods on the same window fixes the misclassification/TypeError risk with no grammar change.
- 主要语言
- TypeScript
- 星标
- 5k
- 派生
- 162
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 12
环境准备
我们还没有检查这个项目的环境配置文件。先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
microsoft/tsdoc 的其他 Issue
-
难度 3/5 1-2 天 新手友好度 35/100
microsoft/tsdoc#470 · 2 条评论 · 6 个 reaction ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 25/100
维护者通常 1 天内回复
-
难度 5/5 一周以上 新手友好度 25/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 35/100
microsoft/tsdoc#442 · 1 个 reaction ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 42/100
维护者通常 1 天内回复
相似的 Issue
-
bug via-triage
难度 2/5 1-3 小时 新手友好度 78/100
pingdotgg/t3code#14452 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
solana-foundation/program-examples#747 · 1 条评论 ·
维护者通常 9 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
remotion-dev/remotion#11847 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
openwatersio/slackwater#355 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 74/100
melgarafael/DeskcommCRM#1998 · 3 条评论 ·
维护者通常 1 天内回复