From: Takashi Sawanaka Date: Sun, 18 Feb 2018 11:18:11 +0000 (+0900) Subject: ccrystaltextview.cpp: Fix infinite loop when replacing ^ sf.net#2094 X-Git-Tag: 2.16.5~758 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=65b2a305c25328a0450ee6b63c6ed58c96990314;p=winmerge-jp%2Fwinmerge-jp.git ccrystaltextview.cpp: Fix infinite loop when replacing ^ sf.net#2094 --- diff --git a/Externals/crystaledit/editlib/ccrystaltextview.cpp b/Externals/crystaledit/editlib/ccrystaltextview.cpp index 5358fb8f9..7a93f075f 100644 --- a/Externals/crystaledit/editlib/ccrystaltextview.cpp +++ b/Externals/crystaledit/editlib/ccrystaltextview.cpp @@ -156,7 +156,7 @@ IMPLEMENT_DYNCREATE (CCrystalTextView, CView) HINSTANCE CCrystalTextView::s_hResourceInst = NULL; -static ptrdiff_t FindStringHelper(LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch); +static ptrdiff_t FindStringHelper(LPCTSTR pszLineBegin, LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch); BEGIN_MESSAGE_MAP (CCrystalTextView, CView) //{{AFX_MSG_MAP(CCrystalTextView) @@ -1690,27 +1690,30 @@ CCrystalTextView::GetMarkerTextBlocks(int nLineIndex) const blocks[0].m_nBgColorIndex = COLORINDEX_NONE; ++nBlocks; const TCHAR *pszChars = GetLineChars(nLineIndex); + int nLineLength = GetLineLength(nLineIndex); if (pszChars) { - for (const TCHAR *p = pszChars; ; ) + for (const TCHAR *p = pszChars; p < pszChars + nLineLength; ) { RxNode *node = nullptr; RxMatchRes matches; int nMatchLen = 0; - size_t nPos = ::FindStringHelper(p, marker.second.sFindWhat, marker.second.dwFlags | FIND_NO_WRAP, nMatchLen, node, &matches); + size_t nPos = ::FindStringHelper(pszChars, p, marker.second.sFindWhat, marker.second.dwFlags | FIND_NO_WRAP, nMatchLen, node, &matches); if (nPos == -1) break; - ASSERT(((p - pszChars) + nPos) < INT_MAX); + if (nLineLength < (p - pszChars) + nPos + nMatchLen) + nMatchLen = static_cast(nLineLength - (p - pszChars)); + ASSERT(((p - pszChars) + nPos) < INT_MAX); blocks[nBlocks].m_nCharPos = static_cast((p - pszChars) + nPos); blocks[nBlocks].m_nBgColorIndex = marker.second.nBgColorIndex | COLORINDEX_APPLYFORCE; blocks[nBlocks].m_nColorIndex = COLORINDEX_NONE; ++nBlocks; - ASSERT(((p - pszChars) + nPos + nMatchLen) < INT_MAX); + ASSERT(((p - pszChars) + nPos + nMatchLen) < INT_MAX); blocks[nBlocks].m_nCharPos = static_cast((p - pszChars) + nPos + nMatchLen); blocks[nBlocks].m_nBgColorIndex = COLORINDEX_NONE; blocks[nBlocks].m_nColorIndex = COLORINDEX_NONE; ++nBlocks; - p += nPos + nMatchLen; + p += nPos + (nMatchLen == 0 ? 1 : nMatchLen); } blocks.resize(nBlocks); allblocks = MergeTextBlocks(allblocks, blocks); @@ -4804,25 +4807,24 @@ PrepareDragData () } static ptrdiff_t -FindStringHelper (LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch) +FindStringHelper (LPCTSTR pszLineBegin, LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch) { if (dwFlags & FIND_REGEXP) { - ptrdiff_t pos; + ptrdiff_t pos = -1; if (rxnode) RxFree (rxnode); + rxnode = nullptr; + if (pszFindWhat[0] == '^' && pszLineBegin != pszFindWhere) + return pos; rxnode = RxCompile (pszFindWhat, (dwFlags & FIND_MATCH_CASE) != 0 ? RX_CASE : 0); if (rxnode && RxExec (rxnode, pszFindWhere, _tcslen (pszFindWhere), pszFindWhere, rxmatch)) { pos = rxmatch->Open[0]; - ASSERT((rxmatch->Close[0] - rxmatch->Open[0]) < INT_MAX); + ASSERT((rxmatch->Close[0] - rxmatch->Open[0]) < INT_MAX); nLen = static_cast(rxmatch->Close[0] - rxmatch->Open[0]); } - else - { - pos = -1; - } return pos; } else @@ -5048,20 +5050,20 @@ FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPosition, size_t nPos; do { - nPos = ::FindStringHelper(line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch); - if( nPos != -1 ) + nPos = ::FindStringHelper(line, line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch); + if( nPos != -1) { nFoundPos = (nFoundPos == -1)? nPos : nFoundPos + nPos; - nFoundPos+= nMatchLen; - line = line.Right( static_cast(nLineLen - (nMatchLen + nPos)) ); + nMatchLen = m_nLastFindWhatLen; + line = line.Right( static_cast(nLineLen - ((nMatchLen == 0 ? 1 : nMatchLen) + nPos)) ); nLineLen = line.GetLength(); } } - while( nPos != -1 ); + while( nPos != -1 && nLineLen != 0); if( nFoundPos != -1 ) // Found text! { - ptCurrentPos.x = static_cast(nFoundPos - nMatchLen); + ptCurrentPos.x = static_cast(nFoundPos); *pptFoundPos = ptCurrentPos; return true; } @@ -5100,11 +5102,6 @@ FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPosition, { line += _T ('\n'); } - else - { - pszChars += ptCurrentPos.x; - nLineLength -= ptCurrentPos.x; - } if (nLineLength > 0) { LPTSTR pszBuf = item.GetBuffer (nLineLength + 1); @@ -5126,7 +5123,6 @@ FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPosition, } LPCTSTR pszChars = GetLineChars (ptCurrentPos.y); - pszChars += ptCurrentPos.x; // Prepare necessary part of line LPTSTR pszBuf = line.GetBuffer (nLineLength + 1); @@ -5135,7 +5131,7 @@ FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPosition, } // Perform search in the line - size_t nPos = ::FindStringHelper (line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch); + size_t nPos = ::FindStringHelper (line, static_cast(line) + ptCurrentPos.x, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch); if (nPos != -1) { if (m_pszMatched) @@ -6554,7 +6550,7 @@ SetTextTypeByContent (LPCTSTR pszContent) RxNode *rxnode = NULL; RxMatchRes rxmatch; int nLen; - if (::FindStringHelper(pszContent, _T("^\\s*\\<\\?xml\\s+.+?\\?\\>\\s*$"), + if (::FindStringHelper(pszContent, pszContent, _T("^\\s*\\<\\?xml\\s+.+?\\?\\>\\s*$"), FIND_REGEXP, nLen, rxnode, &rxmatch) == 0) { if (rxnode)