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
This commit is contained in:
glepnir
2025-06-12 06:31:48 +08:00
committed by GitHub
parent 6a71239cd5
commit 6bee2f686f

View File

@ -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);