summaryrefslogtreecommitdiff
path: root/src/input_handler.cc
diff options
context:
space:
mode:
authorJohannes Altmanninger <aclopte@gmail.com>2024-08-28 15:47:27 +0200
committerMaxime Coste <mawww@kakoune.org>2024-09-02 19:46:33 +1000
commit6e5bc9dd6c477a71020dcbe6c7a387673825d941 (patch)
tree0ba00e8d741f4ffb82514980cfad60b477b51155 /src/input_handler.cc
parent9275d965a6952d44035fd0502ee0d3991352c460 (diff)
Fix <c-r> use-after-free InsertCompletionHide touches used register
Before performing the insertion, InsertCompleter::insert calls try_accept() to accept any selected completion candidate. If there is one, we fire InsertCompletionHide. If that one modifies the register used by <c-r>, the inserted StringViews will be dangling. Fix this by running try_insert first, and read from the register later. Note that we call try_accept() twice but that's fine. It would probably make more sense to copy the register before calling insert() but I don't think it matters. Closes #5220
Diffstat (limited to 'src/input_handler.cc')
-rw-r--r--src/input_handler.cc10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/input_handler.cc b/src/input_handler.cc
index aa43783e..85a8fbc1 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -15,6 +15,7 @@
#include "window.hh"
#include "word_db.hh"
+#include <concepts>
#include <utility>
#include <limits>
@@ -1310,7 +1311,7 @@ public:
auto cp = key.codepoint();
if (not cp or key == Key::Escape)
return;
- insert(RegisterManager::instance()[*cp].get(context()));
+ insert([&] { return RegisterManager::instance()[*cp].get(context()); });
}, "enter register name", register_doc.str());
update_completions = false;
}
@@ -1430,6 +1431,13 @@ private:
}, false);
}
+ template<std::invocable Func>
+ void insert(Func&& lazy_strings)
+ {
+ m_completer.try_accept();
+ insert(std::forward<Func>(lazy_strings)());
+ }
+
void insert(Codepoint key)
{
String str{key};