OSDN Git Service

ccrystaltextview.cpp: Fix infinite loop when replacing ^ sf.net#2094
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 18 Feb 2018 11:18:11 +0000 (20:18 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 18 Feb 2018 11:18:11 +0000 (20:18 +0900)
Externals/crystaledit/editlib/ccrystaltextview.cpp

index 5358fb8..7a93f07 100644 (file)
@@ -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<int>(nLineLength - (p - pszChars));
+              ASSERT(((p - pszChars) + nPos) < INT_MAX);
               blocks[nBlocks].m_nCharPos = static_cast<int>((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<int>((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<int>(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<LONG>(nLineLen - (nMatchLen + nPos)) );
+                      nMatchLen = m_nLastFindWhatLen;
+                      line = line.Right( static_cast<LONG>(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<int>(nFoundPos - nMatchLen);
+                  ptCurrentPos.x = static_cast<int>(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<LPCTSTR>(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)