From ef42bb46c5182037e276ceb251e604b1bcff8f38 Mon Sep 17 00:00:00 2001 From: Neil Date: Fri, 15 Dec 2023 21:35:28 +1100 Subject: Bug [#2289]. Protect SCI_REPLACETARGET* from application changing target in notification handlers. --- src/Editor.cxx | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'src') 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(); } -- cgit v1.2.3