In add_mark() located in src/mark.c, lpos is allocated via list_alloc() at line 1475. After populating it with position data, a chain of dict_add_* calls is evaluated with short-circuit || at lines 1484-1486:
lpos = list_alloc(); if (lpos == NULL) return FAIL; list_append_number(lpos, bufnr); list_append_number(lpos, pos->lnum); list_append_number(lpos, pos->col < MAXCOL ? pos->col + 1 : MAXCOL); list_append_number(lpos, pos->coladd); if (dict_add_string(d, "mark", mname) == FAIL || dict_add_list(d, "pos", lpos) == FAIL || (fname != NULL && dict_add_string(d, "file", fname) == FAIL)) return FAIL; // lpos is leaked
If dict_add_string(d, "mark", mname) fails, dict_add_list(d, "pos", lpos) is never called due to short-circuit evaluation. lpos has no owner and is leaked on return FAIL.
When dict_add_list is called and succeeds, it increments lpos->lv_refcount to 1, transferring ownership to the dict. If dict_add_list itself fails, its internal dictitem_free cleans up and decrements the refcount, freeing the list. So the leak only occurs when dict_add_list is never reached.
On the failure path, check whether lpos was transferred to the dict by inspecting its lv_refcount. If it is still 0, it was never added and must be freed explicitly. The fix is included in the commit.
https://github.com/vim/vim/pull/19827
(1 file)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
thanks
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()