From b42c48e91918388e6b8eaaba36f4521441128a00 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Wed, 20 Apr 2011 11:42:27 -0700 Subject: Disallow notes within notes in reST and markdown. These previously caused infinite looping and stack overflows. For example: [^1] [^1]: See [^1] Note references are allowed in reST notes, so this isn't a full implementation of reST. That can come later. For now we need to prevent the stack overflows. Partially resolves Issue #297. --- src/Text/Pandoc/Readers/Markdown.hs | 9 ++++++++- src/Text/Pandoc/Readers/RST.hs | 16 +++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'src/Text') diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index d284fb25e..1b408dcb2 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -1187,7 +1187,14 @@ note = try $ do let notes = stateNotes state case lookup ref notes of Nothing -> fail "note not found" - Just raw -> liftM Note $ parseFromString parseBlocks raw + Just raw -> do + -- We temporarily empty the note list while parsing the note, + -- so that we don't get infinite loops with notes inside notes... + -- Note references inside other notes do not work. + updateState $ \st -> st{ stateNotes = [] } + contents <- parseFromString parseBlocks raw + updateState $ \st -> st{ stateNotes = notes } + return $ Note contents inlineNote :: GenParser Char ParserState Inline inlineNote = try $ do diff --git a/src/Text/Pandoc/Readers/RST.hs b/src/Text/Pandoc/Readers/RST.hs index 04bb33023..844b4e5b8 100644 --- a/src/Text/Pandoc/Readers/RST.hs +++ b/src/Text/Pandoc/Readers/RST.hs @@ -866,10 +866,16 @@ note = try $ do case lookup ref notes of Nothing -> fail "note not found" Just raw -> do + -- We temporarily empty the note list while parsing the note, + -- so that we don't get infinite loops with notes inside notes... + -- Note references inside other notes are allowed in reST, but + -- not yet in this implementation. + updateState $ \st -> st{ stateNotes = [] } contents <- parseFromString parseBlocks raw - when (ref == "*" || ref == "#") $ do -- auto-numbered - -- delete the note so the next auto-numbered note - -- doesn't get the same contents: - let newnotes = deleteFirstsBy (==) notes [(ref,raw)] - updateState $ \st -> st{ stateNotes = newnotes } + let newnotes = if (ref == "*" || ref == "#") -- auto-numbered + -- delete the note so the next auto-numbered note + -- doesn't get the same contents: + then deleteFirstsBy (==) notes [(ref,raw)] + else notes + updateState $ \st -> st{ stateNotes = newnotes } return $ Note contents -- cgit v1.2.3