Commit: patch 9.2.0770: dict_add_dict() has inconsistent ownership on failure

0 views
Skip to first unread message

Christian Brabandt

unread,
Jul 2, 2026, 4:15:15 PM (8 hours ago) Jul 2
to vim...@googlegroups.com
patch 9.2.0770: dict_add_dict() has inconsistent ownership on failure

Commit: https://github.com/vim/vim/commit/12dbe788d461f7f01a908e9e9ecc844f85d71cb4
Author: Christian Brabandt <c...@256bit.org>
Date: Thu Jul 2 19:30:45 2026 +0000

patch 9.2.0770: dict_add_dict() has inconsistent ownership on failure

Problem: dict_add_dict() frees the passed dict on one failure path
(when dict_add() fails) but not on the other (when
dictitem_alloc() fails), so a caller cannot tell whether it
still owns the dict after a failure. Callers that unref the
dict on failure (e.g. in window.c) then double-free it when
dict_add() fails.
Solution: Make the failure contract consistent: on failure leave the
passed dict untouched and owned by the caller; only take a
reference on success.

related: #20668

Supported by AI.

Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/dict.c b/src/dict.c
index aea40b338..c34ce2981 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -621,12 +621,15 @@ dict_add_dict(dict_T *d, char *key, dict_T *dict)
return FAIL;
item->di_tv.v_type = VAR_DICT;
item->di_tv.vval.v_dict = dict;
- ++dict->dv_refcount;
if (dict_add(d, item) == FAIL)
{
+ // Detach "dict" so dictitem_free() does not unref it: on failure
+ // ownership stays with the caller.
+ item->di_tv.vval.v_dict = NULL;
dictitem_free(item);
return FAIL;
}
+ ++dict->dv_refcount;
return OK;
}

diff --git a/src/version.c b/src/version.c
index 0b3f91193..c50ea4162 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 770,
/**/
769,
/**/
Reply all
Reply to author
Forward
0 new messages