git.iko.soy/typeable/pandoc
on master help sign in
Limit nesting of strong/emph.

This avoids exponential lookahead in parasitic cases, like a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**. Added stateMaxNestingLevel to ParserState. We set this to 6, so you can still have Emph inside Emph, just not indefinitely.

commit7a602d222f6ba005a901d6b3322f9392602d6b9d authorJohn MacFarlane <fiddlosopher@gmail.com> dateTue 7 Feb 2012, 21:50 (15 years ago) parent12aa83f
2 files changed+16−2
src/Text/Pandoc/Parsing.hs+2 src/Text/Pandoc/Readers/Markdown.hs+14−2
src/Text/Pandoc/Parsing.hs+2
@@ -629,6 +629,7 @@ data ParserState = ParserState
629629 { stateParseRaw :: Bool, -- ^ Parse raw HTML and LaTeX?
630630 stateParserContext :: ParserContext, -- ^ Inside list?
631631 stateQuoteContext :: QuoteContext, -- ^ Inside quoted environment?
632+ stateMaxNestingLevel :: Int, -- ^ Max # of nested Strong/Emph
632633 stateLastStrPos :: Maybe SourcePos, -- ^ Position after last str parsed
633634 stateKeys :: KeyTable, -- ^ List of reference keys
634635 stateCitations :: [String], -- ^ List of available citations
@@ -660,6 +661,7 @@ defaultParserState =
660661 ParserState { stateParseRaw = False,
661662 stateParserContext = NullState,
662663 stateQuoteContext = NoQuote,
664+ stateMaxNestingLevel = 6,
663665 stateLastStrPos = Nothing,
664666 stateKeys = M.empty,
665667 stateCitations = [],
src/Text/Pandoc/Readers/Markdown.hs+14−2
@@ -1041,8 +1041,20 @@ inlinesBetween start end =
10411041 where inner = innerSpace <|> (notFollowedBy' whitespace >> inline)
10421042 innerSpace = try $ whitespace >>~ notFollowedBy' end
10431043
1044+-- This is used to prevent exponential blowups for things like:
1045+-- a**a*a**a*a**a*a**a*a**a*a**a*a**
1046+nested :: GenParser Char ParserState a
1047+ -> GenParser Char ParserState a
1048+nested p = do
1049+ nestlevel <- stateMaxNestingLevel `fmap` getState
1050+ guard $ nestlevel > 0
1051+ updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }
1052+ res <- p
1053+ updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }
1054+ return res
1055+
10441056emph :: GenParser Char ParserState Inline
1045−emph = Emph `liftM`
1057+emph = Emph `fmap` nested
10461058 (inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
10471059 where starStart = char '*' >> lookAhead nonspaceChar
10481060 starEnd = notFollowedBy' strong >> char '*'
@@ -1050,7 +1062,7 @@ emph = Emph `liftM`
10501062 ulEnd = notFollowedBy' strong >> char '_'
10511063
10521064strong :: GenParser Char ParserState Inline
1053−strong = Strong `liftM`
1065+strong = Strong `liftM` nested
10541066 (inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
10551067 where starStart = string "**" >> lookAhead nonspaceChar
10561068 starEnd = try $ string "**"