neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 6bee2f686fcfd190e7017fc08115de247ac9afe9
parent 6a71239cd5ea2a8e993bddd8e7765d1afe3e79e4
Author: glepnir <glephunter@gmail.com>
Date:   Thu, 12 Jun 2025 06:31:48 +0800

fix(shada): prevent use-after-free when mapping file marks (#34446)

Problem: When ignore_buf skips buffers during initialization,
shada_read_when_writing uses entry.data.filemark.fname directly
as map key, but later frees the entry, leaving dangling pointers.

Solution: Always create independent copies of filenames as map keys
using xstrdup() for new items, and free all keys during cleanup.

Fix #34440
Diffstat:
Msrc/nvim/shada.c | 17++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/nvim/shada.c b/src/nvim/shada.c @@ -1906,7 +1906,11 @@ static inline ShaDaWriteResult shada_read_when_writing(FileDescriptor *const sd_ } const char *const fname = entry.data.filemark.fname; cstr_t *key = NULL; - ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, NULL); + bool new_item = false; + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, &new_item); + if (new_item) { + *key = xstrdup(fname); + } if (*val == NULL) { *val = xcalloc(1, sizeof(FileMarks)); } @@ -2530,7 +2534,12 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer, } const void *local_marks_iter = NULL; const char *const fname = buf->b_ffname; - ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, NULL, NULL); + cstr_t *map_key = NULL; + bool new_item = false; + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &map_key, &new_item); + if (new_item) { + *map_key = xstrdup(fname); + } if (*val == NULL) { *val = xcalloc(1, sizeof(FileMarks)); } @@ -2711,7 +2720,9 @@ shada_write_exit: hms_dealloc(&wms->hms[i]); } } - map_foreach_value(&wms->file_marks, val, { + const char *stored_key = NULL; + map_foreach(&wms->file_marks, stored_key, val, { + xfree((char *)stored_key); xfree(val); }) map_destroy(cstr_t, &wms->file_marks);