diff options
| author | glepnir <glephunter@gmail.com> | 2025-06-12 06:31:48 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-11 22:31:48 +0000 |
| commit | 6bee2f686fcfd190e7017fc08115de247ac9afe9 (patch) | |
| tree | 746b254e9ab7b8300d4845e279c9b8adb43f857e /src/nvim | |
| parent | 6a71239cd5ea2a8e993bddd8e7765d1afe3e79e4 (diff) | |
| download | rneovim-6bee2f686fcfd190e7017fc08115de247ac9afe9.tar.gz rneovim-6bee2f686fcfd190e7017fc08115de247ac9afe9.tar.bz2 rneovim-6bee2f686fcfd190e7017fc08115de247ac9afe9.zip | |
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 (limited to 'src/nvim')
| -rw-r--r-- | src/nvim/shada.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 2e887fab10..8ea54a6923 100644 --- 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); |