mirror of
https://github.com/mawww/kakoune.git
synced 2024-11-27 02:23:26 +03:00
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
This commit is contained in:
parent
9275d965a6
commit
6e5bc9dd6c
@ -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};
|
||||
|
1
test/hooks/completion-hide-using-register/cmd
Normal file
1
test/hooks/completion-hide-using-register/cmd
Normal file
@ -0,0 +1 @@
|
||||
|
1
test/hooks/completion-hide-using-register/in
Normal file
1
test/hooks/completion-hide-using-register/in
Normal file
@ -0,0 +1 @@
|
||||
echo
|
2
test/hooks/completion-hide-using-register/out
Normal file
2
test/hooks/completion-hide-using-register/out
Normal file
@ -0,0 +1,2 @@
|
||||
echofoobar
|
||||
echo
|
8
test/hooks/completion-hide-using-register/rc
Normal file
8
test/hooks/completion-hide-using-register/rc
Normal file
@ -0,0 +1,8 @@
|
||||
set-option global autocomplete insert
|
||||
hook global InsertCompletionHide .+ %{
|
||||
evaluate-commands -draft -save-regs '"' %{
|
||||
select %val{hook_param}
|
||||
set-register dquote foo bar
|
||||
execute-keys <a-p>
|
||||
}
|
||||
}
|
7
test/hooks/completion-hide-using-register/script
Normal file
7
test/hooks/completion-hide-using-register/script
Normal file
@ -0,0 +1,7 @@
|
||||
ui_out -until '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "Oe" ] }'
|
||||
ui_out -until '{ "jsonrpc": "2.0", "method": "menu_show", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "echo" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out" }]], { "line": 0, "column": 0 }, { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "white", "underline": "default", "attributes": [] }, "inline"] }'
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "<c-n>" ] }'
|
||||
ui_out -until '{ "jsonrpc": "2.0", "method": "menu_select", "params": [1] }'
|
||||
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "<c-r>\"" ] }'
|
||||
ui_out -until '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
|
Loading…
Reference in New Issue
Block a user