aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/extmark.c
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2023-04-27 17:30:22 +0100
committerGitHub <noreply@github.com>2023-04-27 17:30:22 +0100
commiteb4676c67f5dd54bcda473783315901a3444b40b (patch)
treeb57dd8342e3de756031664188ab542ead9134c38 /src/nvim/extmark.c
parent9f29176033926b81553985deaba0ea162ca40215 (diff)
downloadrneovim-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.c17
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)