diff options
-rw-r--r-- | doc/ScintillaHistory.html | 5 | ||||
-rw-r--r-- | src/Editor.cxx | 28 |
2 files changed, 24 insertions, 9 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index ca780bc46..00023b102 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -625,6 +625,11 @@ With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE. </li> + <li> + Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from + application changing target in notification handlers. + <a href="https://sourceforge.net/p/scintilla/bugs/2289/">Bug #2289</a>. + </li> </ul> <h3> <a href="https://www.scintilla.org/scintilla540.zip">Release 5.4.0</a> diff --git a/src/Editor.cxx b/src/Editor.cxx index ceaa1398d..28d680d7a 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -5776,13 +5776,17 @@ Sci::Position Editor::GetTag(char *tagValue, int tagNumber) { Sci::Position Editor::ReplaceTarget(ReplaceType replaceType, std::string_view text) { UndoGroup ug(pdoc); + + std::string substituted; // Copy in case of re-entrance + if (replaceType == ReplaceType::patterns) { Sci::Position length = text.length(); const char *p = pdoc->SubstituteByPosition(text.data(), &length); if (!p) { return 0; } - text = std::string_view(p, length); + substituted.assign(p, length); + text = substituted; } if (replaceType == ReplaceType::minimal) { @@ -5797,19 +5801,25 @@ Sci::Position Editor::ReplaceTarget(ReplaceType replaceType, std::string_view te targetRange = SelectionSegment(start, SelectionPosition(range.end)); } + // Make a copy of targetRange in case callbacks use target + SelectionSegment replaceRange = targetRange; + // Remove the text inside the range - if (targetRange.Length() > 0) - pdoc->DeleteChars(targetRange.start.Position(), targetRange.Length()); - targetRange.end = targetRange.start; + if (replaceRange.Length() > 0) + pdoc->DeleteChars(replaceRange.start.Position(), replaceRange.Length()); // Realize virtual space of target start - const Sci::Position startAfterSpaceInsertion = RealizeVirtualSpace(targetRange.start.Position(), targetRange.start.VirtualSpace()); - targetRange.start.SetPosition(startAfterSpaceInsertion); - targetRange.end = targetRange.start; + const Sci::Position startAfterSpaceInsertion = RealizeVirtualSpace(replaceRange.start.Position(), replaceRange.start.VirtualSpace()); + replaceRange.start.SetPosition(startAfterSpaceInsertion); + replaceRange.end = replaceRange.start; // Insert the new text - const Sci::Position lengthInserted = pdoc->InsertString(targetRange.start.Position(), text); - targetRange.end.SetPosition(targetRange.start.Position() + lengthInserted); + const Sci::Position lengthInserted = pdoc->InsertString(replaceRange.start.Position(), text); + replaceRange.end.SetPosition(replaceRange.start.Position() + lengthInserted); + + // Copy back to targetRange in case application is chaining modifications + targetRange = replaceRange; + return text.length(); } |