vim-patch:9.2.0794: extend() and extendnew() don't handle NULL expr2 properly (#40814)

Problem:  extend() and extendnew() don't handle NULL expr2 properly
          (Mao-Yining)
Solution: Still set the return value when expr2 is NULL (zeertzjq).

fixes:  vim/vim#20758
closes: vim/vim#20759

e397c82a04
This commit is contained in:
zeertzjq
2026-07-18 23:09:45 +08:00
committed by GitHub
parent c6d885b0a6
commit 8a87b4cc67
2 changed files with 33 additions and 8 deletions

View File

@@ -584,12 +584,6 @@ static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new,
assert(locked == true);
return;
}
dict_T *const d2 = argvars[1].vval.v_dict;
if (d2 == NULL) {
// Do nothing
tv_copy(&argvars[0], rettv);
return;
}
if (!is_new && value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
return;
@@ -602,6 +596,11 @@ static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new,
}
}
dict_T *const d2 = argvars[1].vval.v_dict;
if (d2 == NULL) {
goto theend;
}
const char *action = "force";
// Check the third argument.
if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -631,6 +630,7 @@ static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new,
tv_dict_extend(d1, d2, action);
theend:
if (is_new) {
*rettv = (typval_T){
.v_type = VAR_DICT,
@@ -651,7 +651,6 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new,
bool error = false;
list_T *l1 = argvars[0].vval.v_list;
list_T *const l2 = argvars[1].vval.v_list;
if (!is_new && value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
return;
@@ -664,6 +663,11 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new,
}
}
list_T *const l2 = argvars[1].vval.v_list;
if (l2 == NULL) {
goto theend;
}
listitem_T *item;
if (argvars[2].v_type != VAR_UNKNOWN) {
int before = (int)tv_get_number_chk(&argvars[2], &error);
@@ -684,6 +688,7 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new,
}
tv_list_extend(l1, l2, item);
theend:
if (is_new) {
*rettv = (typval_T){
.v_type = VAR_LIST,

View File

@@ -1168,7 +1168,12 @@ func Test_listdict_extend()
LET l = [1, 2, 3]
call extend(l, [4, 5, 6], -3)
call assert_equal([4, 5, 6, 1, 2, 3], l)
call assert_equal([4, 5, 6, 1, 2, 3], l)
LET l = [1, 2, 3]
call assert_equal([1, 2, 3], l->extend([]))
call assert_equal([1, 2, 3], l->extend(v:_null_list))
call assert_equal([1, 2, 3], l)
END
call CheckLegacyAndVim9Success(lines)
@@ -1198,6 +1203,11 @@ func Test_listdict_extend()
LET d = {'a': 'A', 'b': 9}
call extend(d, {'b': 0, 'c': 'C'}, "keep")
call assert_equal({'a': 'A', 'b': 9, 'c': 'C'}, d)
LET d = {'a': 'A', 'b': 9}
call assert_equal({'a': 'A', 'b': 9}, d->extend({}))
call assert_equal({'a': 'A', 'b': 9}, d->extend(v:_null_dict))
call assert_equal({'a': 'A', 'b': 9}, d)
END
call CheckLegacyAndVim9Success(lines)
@@ -1241,6 +1251,11 @@ func Test_listdict_extendnew()
call assert_equal([1, 2, 3], l)
lockvar l
call assert_equal([1, 2, 3, 4, 5], extendnew(l, [4, 5]))
let l2 = extendnew(l, v:_null_list)
call assert_equal([1, 2, 3], l2)
let l2 += [4]
call assert_equal([1, 2, 3, 4], l2)
call assert_equal([1, 2, 3], l)
" Test extendnew() with dictionaries.
let d = {'a': {'b': 'B'}}
@@ -1248,6 +1263,11 @@ func Test_listdict_extendnew()
call assert_equal({'a': {'b': 'B'}}, d)
lockvar d
call assert_equal({'a': {'b': 'B'}, 'c': 'cc'}, extendnew(d, {'c': 'cc'}))
let d2 = extendnew(d, v:_null_dict)
call assert_equal({'a': {'b': 'B'}}, d2)
let d2['c'] = 'C'
call assert_equal({'a': {'b': 'B'}, 'c': 'C'}, d2)
call assert_equal({'a': {'b': 'B'}}, d)
endfunc
func s:check_scope_dict(x, fixed)