Clone
ixen
committed
on 17 Nov 20
Fixed problem with TString::Replace() method corrupting memory (CH-366)
src/libstring/TString.cpp (+3 -1)
553 553                         size_t stStartPos = 0;
554 554                         size_t stFindPos = 0;
555 555                         size_t stSizeDiff = 0;
556 556                         while ((stFindPos = Find(pszWhat, stStartPos)) != npos)
557 557                         {
558 558                                 stSizeDiff += stWithWhatLen - stWhatLen;
559 559                                 stStartPos = stFindPos + stWhatLen;      // offset by what_len because we don't replace anything at this point
560 560                         }
561 561
562 562                         if (stSizeDiff > 0)
563 563                                 stNewLen = stThisLen + stSizeDiff + 1;
564 564                 }
565 565
566 566                 Reserve(stNewLen);
567 567
568 568                 // replace
569 569                 size_t stStartPos = 0;
570 570                 size_t stFindPos = 0;
571 571                 while ((stFindPos = Find(pszWhat, stStartPos)) != npos)
572 572                 {
  573                         stThisLen = GetLength();
  574
573 575                         // Sample string "ABCdddb" (len:6), searching for "dd" (len 2) to replace with "x" (len 1)
574 576                         // found string pos is: [stFindPos, stFindPos + stWhatLen)  -- sample ref: [3, 3 + 2)
575 577                         // we need to
576 578                         // - move string from position [stFindPos + stWhatLen, stCurrentLength) to position [stFindPos + stWithWhatLen, stCurrentLength + stWithWhatLen - stWhatLen] -- sample ref: [3+2, 6) to [3+1, 5)
577 579                         size_t stCountToCopy = stThisLen - stFindPos - stWhatLen + 1;
578 580
579 581                         memmove_s((void*)(m_pszData + stFindPos + stWithWhatLen), stCountToCopy * sizeof(wchar_t), (void*)(m_pszData + stFindPos + stWhatLen), stCountToCopy * sizeof(wchar_t));
580 582
581 583                         // - copy pszWithWhat to position (stFindPos + stWhatLen)
582 584                         memcpy_s((void*)(m_pszData + stFindPos), stWithWhatLen * sizeof(wchar_t), pszWithWhat, stWithWhatLen * sizeof(wchar_t));
583 585
584 586                         stStartPos = stFindPos + stWithWhatLen// offset by stWithWhatLen because we replaced text
585 587                 }
586 588         }
587 589
588 590         /** Returns a character at a given position. Function is very slow (needs to recalc the size of the TString
589 591          *  and make a few comparisons), but quite safe - if the index is out of range then -1 is returned.
590 592          *  Make sure to interpret the returned character according to unicode flag. If the TString is unicode, then the
591 593          *  character returned is also unicode (and vice versa).
592 594          * \param[in] tPos - index of the character to return.
 
655 657                 }
656 658         }
657 659
658 660         void TString::SetString(const wchar_t* pszString)
659 661         {
660 662                 if (!pszString)
661 663                         Clear();
662 664                 else
663 665                 {
664 666                         size_t stLen = _tcslen(pszString);
665 667                         SetString(pszString, stLen);
666 668                 }
667 669         }
668 670
669 671         void TString::Reserve(size_t stLen)
670 672         {
671 673                 if (!m_pszData || m_stBufferSize < stLen)
672 674                 {
673 675                         size_t stNewLen = stLen;//ROUNDUP(stLen, CHUNK_INCSIZE);
674 676
675                           wchar_t* pszNewBuffer = new wchar_t[stNewLen];
  677                         wchar_t* pszNewBuffer = new wchar_t[stNewLen] { };
676 678                         if (m_pszData && m_pszData[0] != L'\0')
677 679                                 _tcsncpy_s(pszNewBuffer, stNewLen, m_pszData, GetLength() + 1);
678 680                         else
679 681                                 pszNewBuffer[0] = _T('\0');
680 682
681 683                         delete[] m_pszData;
682 684                         m_pszData = pszNewBuffer;
683 685                         m_stBufferSize = stNewLen;
684 686                 }
685 687         }
686 688
687 689         const wchar_t* TString::c_str() const
688 690         {
689 691                 return m_pszData ? m_pszData : L"";
690 692         }
691 693 }
692 694
693 695 string::TString operator+(const wchar_t* pszString, const string::TString& str)
694 696 {
695 697         string::TString strNew(pszString);