Fix IndexError in html_block/heading terminator rules on table-in-blockquote at EOF - #416
Open
saket3395 wants to merge 1 commit into
Open
Conversation
…blebooksgh-415) Input that ends on a blockquote marker while a table is open inside that quote (e.g. "> | a | b |\n> |---|---|\n>") raised IndexError: string index out of range. The table rule runs html_block and heading as terminator rules on the empty final line a trailing '>' produces, where pos = bMarks[startLine] + tShift[startLine] equals len(state.src). Both rules index state.src[pos] without guarding that boundary: html_block at 'if state.src[pos] != "<"' and heading at 'ch = state.src[pos]' (its pos >= maximum check runs on the next line, after the index). In markdown-it (JS) the equivalent charCodeAt(pos) returns NaN out of range instead of raising -- the port hazard from executablebooksGH-190. Sibling terminator rules already defend against exactly this: hr.py and blockquote.py wrap the same index in try/except IndexError -> return False (added for executablebooksGH-185 / executablebooksGH-204). This applies the same guard to the two rules that were missed. Adds regression tests for both crash paths (html_block runs first with html enabled; heading is reached when html is disabled).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #415. Input that ends on a blockquote marker while a table is open inside that quote raises
IndexError: string index out of range:Root cause
With
tableenabled,html_blockandheadingrun as terminator rules on the empty final line that a trailing>produces. There,pos = state.bMarks[startLine] + state.tShift[startLine]equalslen(state.src), and both rules indexstate.src[pos]without guarding that boundary:html_block.py:if state.src[pos] != "<":heading.py:ch = state.src[pos]— itspos >= maximumcheck is on the next line, after the indexIn markdown-it (JS) the equivalent
state.src.charCodeAt(pos)returnsNaNout of range instead of raising — the port hazard tracked in #190.Fix
Sibling terminator rules already defend against exactly this —
hr.pyandblockquote.pywrap the same index access intry: ... except IndexError: return False(added for #185 / #204).html_block.pyandheading.pywere missed. This applies the same established guard to both.html_blockruns beforeheading, so it shadows it (disablinghtmlmoves the traceback toheadingrather than fixing it) — hence both rules need the guard, and there is a regression test for each path.Tests
Added two regression tests in
tests/test_fuzzer.py(the existing home for crash-regression cases), one per crash path — asserting the input renders without raising.Note on local verification
I verified the guard logic in isolation (the old expression raises
IndexErrorwhenpos == len(src); the guarded version returnsFalse, i.e. the rule declines, with identical behavior for in-range characters — matching howhr.py/blockquote.pyalready behave). I was not able to run the full pytest suite locally (my environment's Python predates this package's minimum), so I'd appreciate CI confirming the two new tests pass and that the rendered output for that input is sensible. Happy to adjust the tests to assert exact rendered HTML if you'd prefer that over "does not raise".