patch 8.2.1236: Vim9: a few errors not caught by try/catch
Problem: Vim9: a few errors not caught by try/catch.
Solution: Do not bail out if an error is inside try/catch. Fix that a not
matching catch doesn't jump to :endtry.
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 88979af..ce12781 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1241,7 +1241,7 @@
if (msg != NULL)
{
emsg(_(msg));
- goto failed;
+ goto on_error;
}
}
break;
@@ -1272,7 +1272,8 @@
--ectx.ec_stack.ga_len;
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
== FAIL)
- goto failed;
+ // should not happen, type is checked when compiling
+ goto on_error;
break;
// store g:/b:/w:/t: variable
@@ -1335,7 +1336,7 @@
if (lidx < 0 || lidx > list->lv_len)
{
semsg(_(e_listidx), lidx);
- goto failed;
+ goto on_error;
}
tv = STACK_TV_BOT(-3);
if (lidx < list->lv_len)
@@ -1348,7 +1349,7 @@
}
else
{
- // append to list
+ // append to list, only fails when out of memory
if (list_append_tv(list, tv) == FAIL)
goto failed;
clear_tv(tv);
@@ -1371,18 +1372,19 @@
if (key == NULL || *key == NUL)
{
emsg(_(e_emptykey));
- goto failed;
+ goto on_error;
}
tv = STACK_TV_BOT(-3);
di = dict_find(dict, key, -1);
if (di != NULL)
{
+ // overwrite existing value
clear_tv(&di->di_tv);
di->di_tv = *tv;
}
else
{
- // add to dict
+ // add to dict, only fails when out of memory
if (dict_add_tv(dict, (char *)key, tv) == FAIL)
goto failed;
clear_tv(tv);
@@ -1465,7 +1467,7 @@
case ISN_UNLET:
if (do_unlet(iptr->isn_arg.unlet.ul_name,
iptr->isn_arg.unlet.ul_forceit) == FAIL)
- goto failed;
+ goto on_error;
break;
case ISN_UNLETENV:
vim_unsetenv(iptr->isn_arg.unlet.ul_name);
@@ -1481,24 +1483,38 @@
// create a dict from items on the stack
case ISN_NEWDICT:
{
- int count = iptr->isn_arg.number;
- dict_T *dict = dict_alloc();
- dictitem_T *item;
+ int count = iptr->isn_arg.number;
+ dict_T *dict = dict_alloc();
+ dictitem_T *item;
if (dict == NULL)
goto failed;
for (idx = 0; idx < count; ++idx)
{
- // check key type is VAR_STRING
+ // have already checked key type is VAR_STRING
tv = STACK_TV_BOT(2 * (idx - count));
+ // check key is unique
+ item = dict_find(dict, tv->vval.v_string, -1);
+ if (item != NULL)
+ {
+ semsg(_(e_duplicate_key), tv->vval.v_string);
+ dict_unref(dict);
+ goto on_error;
+ }
item = dictitem_alloc(tv->vval.v_string);
clear_tv(tv);
if (item == NULL)
+ {
+ dict_unref(dict);
goto failed;
+ }
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
item->di_tv.v_lock = 0;
if (dict_add(dict, item) == FAIL)
+ {
+ dict_unref(dict);
goto failed;
+ }
}
if (count > 0)
@@ -1519,7 +1535,7 @@
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
iptr->isn_arg.dfunc.cdf_argcount,
&ectx) == FAIL)
- goto failed;
+ goto on_error;
break;
// call a builtin function