cap nesting depth in MarkdownSlurper to avoid stack overflow#2711
cap nesting depth in MarkdownSlurper to avoid stack overflow#2711netliomax25-code wants to merge 1 commit into
Conversation
✅ All tests passed ✅🏷️ Commit: a2d02c8 Learn more about TestLens at testlens.app. |
|
AI read on your PR below:
|
There was a problem hiding this comment.
Pull request overview
Caps MarkdownSlurper’s traversal nesting depth to prevent deeply nested CommonMark inputs from triggering a StackOverflowError and leaking a raw Error to callers, instead consistently failing with MarkdownRuntimeException (configurable via groovy.markdown.maxNestingDepth).
Changes:
- Added
maxNestingDepth(default 1000) with getter/setter and system-property override, plus an iterative pre-check (checkNestingDepth) before recursive conversion. - Added spec/regression tests ensuring deeply nested Markdown is rejected with
MarkdownRuntimeExceptionand that the cap is configurable.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| subprojects/groovy-markdown/src/main/java/groovy/markdown/MarkdownSlurper.java | Introduces configurable nesting-depth cap and an iterative depth pre-check before recursive tree conversion. |
| subprojects/groovy-markdown/src/spec/test/groovy/markdown/MarkdownSlurperTest.groovy | Adds regression/spec coverage for rejecting pathological nesting and for configurability of the cap. |
| @Test | ||
| void testDeeplyNestedInputRejected() { | ||
| // a small (~5 KB) document nests block quotes thousands deep; the recursive | ||
| // document walk must not be driven into a StackOverflowError | ||
| def md = ('>' * 5000) + ' x' | ||
| def ex = assertThrows(MarkdownRuntimeException) { new MarkdownSlurper().parseText(md) } | ||
| assert ex.message.contains('nesting depth') | ||
| } | ||
|
|
||
| @Test | ||
| void testMaxNestingDepthConfigurable() { | ||
| def slurper = new MarkdownSlurper() | ||
| assert slurper.maxNestingDepth == MarkdownSlurper.DEFAULT_MAX_NESTING_DEPTH | ||
| slurper.maxNestingDepth = 3 | ||
| assertThrows(MarkdownRuntimeException) { slurper.parseText(('>' * 10) + ' x') } | ||
| // input within the limit still parses | ||
| assert slurper.parseText('> quoted').nodes[0].type == 'block_quote' | ||
| } |
|
Subsumed into #2729 |
|
Merged as part of #2729. Thanks! |
Validation: a 5000-deep block-quote input now throws MarkdownRuntimeException instead of overflowing, documents within the limit parse unchanged, and the added regression tests plus the existing MarkdownSlurper suite pass.