From 17b1a606d5ccc86007375d62b89da84b5fc03b22 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 20 Jul 2018 20:06:36 +0800 Subject: [PATCH] PegHighlighter: fix index-out-of-scope issue when parsing results When user inserts many empty lines at once, the increated block number may exceed the range of the parser result. --- src/peghighlighterresult.cpp | 24 ++++++++++++++++++++---- src/peghighlighterresult.h | 2 ++ src/pegmarkdownhighlighter.cpp | 12 ++++++++---- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/peghighlighterresult.cpp b/src/peghighlighterresult.cpp index af6861fe..d7da5a5a 100644 --- a/src/peghighlighterresult.cpp +++ b/src/peghighlighterresult.cpp @@ -120,6 +120,10 @@ void PegHighlighterResult::parseBlocksHighlightOne(QVector> &p_b QTextBlock block = p_doc->findBlock(p_pos); int startBlockNum = block.blockNumber(); int endBlockNum = p_doc->findBlock(p_end).blockNumber(); + if (endBlockNum >= p_blocksHighlights.size()) { + endBlockNum = p_blocksHighlights.size() - 1; + } + while (block.isValid()) { int blockNum = block.blockNumber(); @@ -148,6 +152,7 @@ void PegHighlighterResult::parseBlocksHighlightOne(QVector> &p_b } } +#if 0 void PegHighlighterResult::parseBlocksElementRegionOne(QHash> &p_regs, const QTextDocument *p_doc, unsigned long p_pos, @@ -188,6 +193,7 @@ void PegHighlighterResult::parseBlocksElementRegionOne(QHash &p_result) @@ -200,6 +206,9 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p for (auto it = regs.begin(); it != regs.end(); ++it) { QTextBlock block = doc->findBlock(it.value().m_startPos); int lastBlock = doc->findBlock(it.value().m_endPos - 1).blockNumber(); + if (lastBlock >= p_result->m_numOfBlocks) { + lastBlock = p_result->m_numOfBlocks - 1; + } while (block.isValid()) { int blockNumber = block.blockNumber(); @@ -257,13 +266,11 @@ void PegHighlighterResult::parseMathjaxBlocks(const PegMarkdownHighlighter *p_pe for (auto it = inlineRegs.begin(); it != inlineRegs.end(); ++it) { const VElementRegion &r = *it; QTextBlock block = doc->findBlock(r.m_startPos); - // Inline equation MUST in one block. - Q_ASSERT(block.blockNumber() == doc->findBlock(r.m_endPos - 1).blockNumber()); - if (!block.isValid()) { continue; } + // Inline equation MUST in one block. if (r.m_endPos - block.position() > block.length()) { continue; } @@ -287,6 +294,9 @@ void PegHighlighterResult::parseMathjaxBlocks(const PegMarkdownHighlighter *p_pe const VElementRegion &r = *it; QTextBlock block = doc->findBlock(r.m_startPos); int lastBlock = doc->findBlock(r.m_endPos - 1).blockNumber(); + if (lastBlock >= p_result->m_numOfBlocks) { + lastBlock = p_result->m_numOfBlocks - 1; + } while (block.isValid()) { int blockNum = block.blockNumber(); @@ -308,7 +318,10 @@ void PegHighlighterResult::parseMathjaxBlocks(const PegMarkdownHighlighter *p_pe m_mathjaxBlocks.append(item); } } else { - Q_ASSERT(text.startsWith(marker)); + if (!text.startsWith(marker)) { + break; + } + if (text.size() > 2 && text.endsWith(marker)) { // Within one block. item.m_blockNumber = blockNum; @@ -338,6 +351,9 @@ void PegHighlighterResult::parseHRuleBlocks(const PegMarkdownHighlighter *p_peg, for (auto it = regs.begin(); it != regs.end(); ++it) { QTextBlock block = doc->findBlock(it->m_startPos); int lastBlock = doc->findBlock(it->m_endPos - 1).blockNumber(); + if (lastBlock >= p_result->m_numOfBlocks) { + lastBlock = p_result->m_numOfBlocks - 1; + } while (block.isValid()) { int blockNumber = block.blockNumber(); diff --git a/src/peghighlighterresult.h b/src/peghighlighterresult.h index 95cb0c29..1680ef8c 100644 --- a/src/peghighlighterresult.h +++ b/src/peghighlighterresult.h @@ -94,10 +94,12 @@ private: void parseHRuleBlocks(const PegMarkdownHighlighter *p_peg, const QSharedPointer &p_result); +#if 0 void parseBlocksElementRegionOne(QHash> &p_regs, const QTextDocument *p_doc, unsigned long p_pos, unsigned long p_end); +#endif QRegExp m_codeBlockStartExp; QRegExp m_codeBlockEndExp; diff --git a/src/pegmarkdownhighlighter.cpp b/src/pegmarkdownhighlighter.cpp index cb94f0ad..c53667d4 100644 --- a/src/pegmarkdownhighlighter.cpp +++ b/src/pegmarkdownhighlighter.cpp @@ -209,6 +209,10 @@ void PegMarkdownHighlighter::startFastParse(int p_position, int p_charsRemoved, // Get affected block range. int firstBlockNum, lastBlockNum; getFastParseBlockRange(p_position, p_charsRemoved, p_charsAdded, firstBlockNum, lastBlockNum); + if (firstBlockNum == -1) { + m_fastResult.reset(); + return; + } QString text; QTextBlock block = m_doc->findBlockByNumber(firstBlockNum); @@ -568,7 +572,7 @@ void PegMarkdownHighlighter::getFastParseBlockRange(int p_position, int &p_firstBlock, int &p_lastBlock) const { - const int maxNumOfBlocks = 50; + const int maxNumOfBlocks = 500; int charsChanged = p_charsRemoved + p_charsAdded; QTextBlock firstBlock = m_doc->findBlock(p_position); @@ -580,10 +584,8 @@ void PegMarkdownHighlighter::getFastParseBlockRange(int p_position, } int num = lastBlock.blockNumber() - firstBlock.blockNumber() + 1; - if (num >= maxNumOfBlocks) { - p_firstBlock = firstBlock.blockNumber(); - p_lastBlock = p_firstBlock + maxNumOfBlocks - 1; + p_firstBlock = p_lastBlock = -1; return; } @@ -667,5 +669,7 @@ void PegMarkdownHighlighter::getFastParseBlockRange(int p_position, p_lastBlock = lastBlock.blockNumber(); if (p_lastBlock < p_firstBlock) { p_lastBlock = p_firstBlock; + } else if (p_lastBlock - p_firstBlock + 1 > maxNumOfBlocks) { + p_firstBlock = p_lastBlock = -1; } }