diff --git a/lib/parser_inline.js b/lib/parser_inline.js index e89a71b..b670ba4 100644 --- a/lib/parser_inline.js +++ b/lib/parser_inline.js @@ -69,7 +69,7 @@ function ParserInline() { // returns `true` if any rule reported success // ParserInline.prototype.skipToken = function (state) { - var i, pos = state.pos, + var ok, i, pos = state.pos, rules = this.ruler.getRules(''), len = rules.length, maxNesting = state.md.options.maxNesting, @@ -81,17 +81,21 @@ ParserInline.prototype.skipToken = function (state) { return; } - /*istanbul ignore else*/ if (state.level < maxNesting) { for (i = 0; i < len; i++) { - if (rules[i](state, true)) { - cache[pos] = state.pos; - return; - } + // Increment state.level and decrement it later to limit recursion. + // It's harmless to do here, because no tokens are created. But ideally, + // we'd need a separate private state variable for this purpose. + // + state.level++; + ok = rules[i](state, true); + state.level--; + + if (ok) { break; } } } - state.pos++; + if (!ok) { state.pos++; } cache[pos] = state.pos; }; diff --git a/test/misc.js b/test/misc.js index 1fe0040..a20d495 100644 --- a/test/misc.js +++ b/test/misc.js @@ -269,6 +269,22 @@ describe('maxNesting', function () { ); }); + it('Inline parser should not nest above limit', function () { + var md = markdownit({ maxNesting: 1 }); + assert.strictEqual( + md.render('[`foo`]()'), + '

`foo`

\n' + ); + }); + + it('Inline nesting coverage', function () { + var md = markdownit({ maxNesting: 2 }); + assert.strictEqual( + md.render('[[[[[[[[[[[[[[[[[[foo]()'), + '

[[[[[[[[[[[[[[[[[foo

\n' + ); + }); + });