From b1a714ed44501dd972b7f16e9a0321694832514a Mon Sep 17 00:00:00 2001 From: hluk Date: Sun, 1 Dec 2013 15:09:04 +0100 Subject: [PATCH] FakeVim: Fix infinite loop when replacing empty text Change-Id: Ie4ba6420889b0a6a5712b43a11f8366aa9a30edc Reviewed-by: Eike Ziller Reviewed-by: hjk --- src/plugins/fakevim/fakevim_test.cpp | 11 +++++++++++ src/plugins/fakevim/fakevimhandler.cpp | 14 +++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 6b9144da5d9..c87685e1ea9 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -2206,6 +2206,17 @@ void FakeVimPlugin::test_vim_substitute() COMMAND("'<,'>s/^/*", "abc" N "**def" N X "**ghi" N "jkl"); KEYS("u", "abc" N X "*def" N "*ghi" N "jkl"); KEYS("gv:s/^/+", "abc" N "+*def" N X "+*ghi" N "jkl"); + + // replace empty string + data.setText("abc"); + COMMAND("s//--/g", "--a--b--c"); + + // remove characters + data.setText("abc def"); + COMMAND("s/[abde]//g", "c f"); + COMMAND("undo | s/[bcef]//g", "a d"); + COMMAND("undo | s/\\w//g", " "); + COMMAND("undo | s/f\\|$/-/g", "abc de-"); } void FakeVimPlugin::test_vim_ex_yank() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 7460bb1de79..ed6513da0ae 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -623,10 +623,22 @@ static bool substituteText(QString *text, QRegExp &pattern, const QString &repla { bool substituted = false; int pos = 0; + int right = -1; while (true) { pos = pattern.indexIn(*text, pos, QRegExp::CaretAtZero); if (pos == -1) break; + + // ensure that substitution is advancing towards end of line + if (right == text->size() - pos) { + ++pos; + if (pos == text->size()) + break; + continue; + } + + right = text->size() - pos; + substituted = true; QString matched = text->mid(pos, pattern.cap(0).size()); QString repl; @@ -652,7 +664,7 @@ static bool substituteText(QString *text, QRegExp &pattern, const QString &repla } } text->replace(pos, matched.size(), repl); - pos += qMax(1, repl.size()); + pos += (repl.isEmpty() && matched.isEmpty()) ? 1 : repl.size(); if (pos >= text->size() || !global) break;