From 7545fa58ae318cf6307d81b9fc3124f6a9352730 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 14 Mar 2020 13:49:52 +1100 Subject: [PATCH] Fix invalid access to deleted line when updating insert completion The computation of the completion end position was taking place too early, before we checked if the buffer did get modified. Fixes #3349 --- src/insert_completer.cc | 12 ++++++------ test/regression/3349-crash-in-completion/cmd | 1 + test/regression/3349-crash-in-completion/in | 2 ++ test/regression/3349-crash-in-completion/out | 1 + test/regression/3349-crash-in-completion/rc | 4 ++++ test/regression/3349-crash-in-completion/script | 2 ++ 6 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 test/regression/3349-crash-in-completion/cmd create mode 100644 test/regression/3349-crash-in-completion/in create mode 100644 test/regression/3349-crash-in-completion/out create mode 100644 test/regression/3349-crash-in-completion/rc create mode 100644 test/regression/3349-crash-in-completion/script diff --git a/src/insert_completer.cc b/src/insert_completer.cc index e7818524..f79d6c99 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -267,12 +267,6 @@ InsertCompletion complete_option(const SelectionList& sels, str_to_int({match[2].first, match[2].second}) - 1 }; if (not buffer.is_valid(coord)) return {}; - auto end = cursor_pos; - if (match[3].matched) - { - ByteCount len = str_to_int({match[3].first, match[3].second}); - end = buffer.advance(coord, len); - } size_t timestamp = (size_t)str_to_int({match[4].first, match[4].second}); auto changes = buffer.changes_since(timestamp); if (any_of(changes, [&](auto&& change) { return change.begin < coord; })) @@ -327,6 +321,12 @@ InsertCompletion complete_option(const SelectionList& sels, std::pop_heap(first, last--, greater); } + auto end = cursor_pos; + if (match[3].matched) + { + ByteCount len = str_to_int({match[3].first, match[3].second}); + end = buffer.advance(coord, len); + } return { std::move(candidates), coord, end, timestamp }; } } diff --git a/test/regression/3349-crash-in-completion/cmd b/test/regression/3349-crash-in-completion/cmd new file mode 100644 index 00000000..04e826bd --- /dev/null +++ b/test/regression/3349-crash-in-completion/cmd @@ -0,0 +1 @@ +gei diff --git a/test/regression/3349-crash-in-completion/in b/test/regression/3349-crash-in-completion/in new file mode 100644 index 00000000..2fa19d09 --- /dev/null +++ b/test/regression/3349-crash-in-completion/in @@ -0,0 +1,2 @@ +first +a diff --git a/test/regression/3349-crash-in-completion/out b/test/regression/3349-crash-in-completion/out new file mode 100644 index 00000000..9c59e24b --- /dev/null +++ b/test/regression/3349-crash-in-completion/out @@ -0,0 +1 @@ +first diff --git a/test/regression/3349-crash-in-completion/rc b/test/regression/3349-crash-in-completion/rc new file mode 100644 index 00000000..4ee1b409 --- /dev/null +++ b/test/regression/3349-crash-in-completion/rc @@ -0,0 +1,4 @@ +set-option global autocomplete insert +declare-option -hidden completions my_completions +set-option global completers option=my_completions +set-option global my_completions "2.1+1@%val(timestamp)" "a||a" diff --git a/test/regression/3349-crash-in-completion/script b/test/regression/3349-crash-in-completion/script new file mode 100644 index 00000000..b55170b0 --- /dev/null +++ b/test/regression/3349-crash-in-completion/script @@ -0,0 +1,2 @@ +ui_out -ignore 4 +sleep .2 # trigger insert completion auto update