diff options
author | Lewis Russell <lewis6991@gmail.com> | 2023-04-27 17:30:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-27 17:30:22 +0100 |
commit | eb4676c67f5dd54bcda473783315901a3444b40b (patch) | |
tree | b57dd8342e3de756031664188ab542ead9134c38 /src/nvim/extmark.c | |
parent | 9f29176033926b81553985deaba0ea162ca40215 (diff) | |
download | rneovim-eb4676c67f5dd54bcda473783315901a3444b40b.tar.gz rneovim-eb4676c67f5dd54bcda473783315901a3444b40b.tar.bz2 rneovim-eb4676c67f5dd54bcda473783315901a3444b40b.zip |
fix: disallow removing extmarks in on_lines callbacks (#23219)
fix(extmarks): disallow removing extmarks in on_lines callbacks
decor_redraw_start (which runs before decor_providers_invoke_lines) gets
references for the extmarks on a specific line. If these extmarks are
deleted in on_lines callbacks then this results in a heap-use-after-free
error.
Fixes #22801
Diffstat (limited to 'src/nvim/extmark.c')
-rw-r--r-- | src/nvim/extmark.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 32050c5b41..727be1562c 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -31,6 +31,7 @@ #include <assert.h> #include <sys/types.h> +#include "nvim/api/private/helpers.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/buffer_updates.h" @@ -59,7 +60,7 @@ static uint32_t *buf_ns_ref(buf_T *buf, uint32_t ns_id, bool put) /// must not be used during iteration! void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col, int end_row, colnr_T end_col, Decoration *decor, bool right_gravity, bool end_right_gravity, - ExtmarkOp op) + ExtmarkOp op, Error *err) { uint32_t *ns = buf_ns_ref(buf, ns_id, true); uint32_t id = idp ? *idp : 0; @@ -88,6 +89,13 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col MarkTreeIter itr[1] = { 0 }; mtkey_t old_mark = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, itr); if (old_mark.id) { + if (decor_state.running_on_lines) { + if (err) { + api_set_error(err, kErrorTypeException, + "Cannot change extmarks during on_line callbacks"); + } + goto error; + } if (mt_paired(old_mark) || end_row > -1) { extmark_del(buf, ns_id, id); } else { @@ -162,6 +170,13 @@ revised: if (idp) { *idp = id; } + + return; + +error: + if (decor_full) { + decor_free(decor); + } } static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col) |