Patch 8.2.1813
Problem: Vim9: can assign wrong type to script dict. (Christian J. Robinson)
Solution: Check the type if known.
Files: src/structs.h, src/eval.c, src/vim9script.c,
src/proto/vim9script.pro, src/proto/evalvars.pro,
src/testdir/test_vim9_script.vim
*** ../vim-8.2.1812/src/structs.h 2020-10-03 22:51:42.890813408 +0200
--- src/structs.h 2020-10-08 20:43:44.200016806 +0200
***************
*** 4055,4060 ****
--- 4055,4061 ----
dict_T *ll_dict; // The Dictionary or NULL
dictitem_T *ll_di; // The dictitem or NULL
char_u *ll_newkey; // New key for Dict in alloc. mem or NULL.
+ type_T *ll_valtype; // type expected for the value or NULL
blob_T *ll_blob; // The Blob or NULL
} lval_T;
*** ../vim-8.2.1812/src/eval.c 2020-10-04 16:06:00.513884339 +0200
--- src/eval.c 2020-10-08 21:11:21.356457068 +0200
***************
*** 887,892 ****
--- 887,903 ----
return NULL;
}
+ if (in_vim9script() && lp->ll_valtype == NULL
+ && lp->ll_tv == &v->di_tv
+ && ht != NULL && ht == get_script_local_ht())
+ {
+ svar_T *sv = find_typval_in_script(lp->ll_tv);
+
+ // Vim9 script local variable: get the type
+ if (sv != NULL)
+ lp->ll_valtype = sv->sv_type;
+ }
+
len = -1;
if (*p == '.')
{
***************
*** 1037,1042 ****
--- 1048,1057 ----
}
}
+ if (lp->ll_valtype != NULL)
+ // use the type of the member
+ lp->ll_valtype = lp->ll_valtype->tt_member;
+
if (lp->ll_di == NULL)
{
// Can't add "v:" or "a:" variable.
***************
*** 1148,1153 ****
--- 1163,1172 ----
return NULL;
}
+ if (lp->ll_valtype != NULL)
+ // use the type of the member
+ lp->ll_valtype = lp->ll_valtype->tt_member;
+
/*
* May need to find the item or absolute index for the second
* index of a range.
***************
*** 1383,1388 ****
--- 1402,1412 ----
emsg(_("E996: Cannot lock a list or dict"));
return;
}
+
+ if (lp->ll_valtype != NULL
+ && check_typval_type(lp->ll_valtype, rettv, 0) == FAIL)
+ return;
+
if (lp->ll_newkey != NULL)
{
if (op != NULL && *op != '=')
*** ../vim-8.2.1812/src/vim9script.c 2020-09-26 15:08:52.881779910 +0200
--- src/vim9script.c 2020-10-08 20:54:43.898813084 +0200
***************
*** 565,582 ****
}
/*
! * Check if the type of script variable "dest" allows assigning "value".
! * If needed convert "value" to a bool.
*/
! int
! check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
int idx;
if (si->sn_version != SCRIPT_VERSION_VIM9)
// legacy script doesn't store variable types
! return OK;
// Find the svar_T in sn_var_vals.
for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
--- 565,582 ----
}
/*
! * Find the script-local variable that links to "dest".
! * Returns NULL if not found.
*/
! svar_T *
! find_typval_in_script(typval_T *dest)
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
int idx;
if (si->sn_version != SCRIPT_VERSION_VIM9)
// legacy script doesn't store variable types
! return NULL;
// Find the svar_T in sn_var_vals.
for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
***************
*** 584,611 ****
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
if (sv->sv_tv == dest)
{
! int ret;
! if (sv->sv_const)
! {
! semsg(_(e_readonlyvar), name);
! return FAIL;
! }
! ret = check_typval_type(sv->sv_type, value, 0);
! if (ret == OK && need_convert_to_bool(sv->sv_type, value))
! {
! int val = tv2bool(value);
!
! clear_tv(value);
! value->v_type = VAR_BOOL;
! value->v_lock = 0;
! value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE;
! }
! return ret;
}
}
! iemsg("check_script_var_type(): not found");
return OK; // not really
}
--- 584,625 ----
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
if (sv->sv_tv == dest)
+ return sv;
+ }
+ iemsg("check_script_var_type(): not found");
+ return NULL;
+ }
+
+ /*
+ * Check if the type of script variable "dest" allows assigning "value".
+ * If needed convert "value" to a bool.
+ */
+ int
+ check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
+ {
+ svar_T *sv = find_typval_in_script(dest);
+ int ret;
+
+ if (sv != NULL)
+ {
+ if (sv->sv_const)
+ {
+ semsg(_(e_readonlyvar), name);
+ return FAIL;
+ }
+ ret = check_typval_type(sv->sv_type, value, 0);
+ if (ret == OK && need_convert_to_bool(sv->sv_type, value))
{
! int val = tv2bool(value);
! clear_tv(value);
! value->v_type = VAR_BOOL;
! value->v_lock = 0;
! value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE;
}
+ return ret;
}
!
return OK; // not really
}
*** ../vim-8.2.1812/src/proto/vim9script.pro 2020-07-28 20:06:46.115280293
+0200
--- src/proto/vim9script.pro 2020-10-08 20:58:31.962304124 +0200
***************
*** 8,12 ****
--- 8,13 ----
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type);
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid,
evalarg_T *evalarg, void *cctx);
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
+ svar_T *find_typval_in_script(typval_T *dest);
int check_script_var_type(typval_T *dest, typval_T *value, char_u *name);
/* vim: set ft=c : */
*** ../vim-8.2.1812/src/proto/evalvars.pro 2020-09-26 15:08:52.881779910
+0200
--- src/proto/evalvars.pro 2020-10-08 20:59:09.030219067 +0200
***************
*** 58,63 ****
--- 58,64 ----
void check_vars(char_u *name, int len);
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int
no_autoload);
+ hashtab_T *get_script_local_ht(void);
void *lookup_scriptvar(char_u *name, size_t len, cctx_T *dummy);
hashtab_T *find_var_ht(char_u *name, char_u **varname);
char_u *get_var_value(char_u *name);
*** ../vim-8.2.1812/src/testdir/test_vim9_script.vim 2020-10-04
16:06:00.513884339 +0200
--- src/testdir/test_vim9_script.vim 2020-10-08 21:15:39.751793995 +0200
***************
*** 145,150 ****
--- 145,159 ----
CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:')
enddef
+ def Test_script_wrong_type()
+ var lines =<< trim END
+ vim9script
+ var s:dict: dict<string>
+ s:dict['a'] = ['x']
+ END
+ CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got
list<string>', 3)
+ enddef
+
def Test_const()
CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:')
CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:')
*** ../vim-8.2.1812/src/version.c 2020-10-07 19:08:00.013793470 +0200
--- src/version.c 2020-10-08 21:16:16.847699389 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1813,
/**/
--
The real
trick is
this: to
keep the
lines as
short as
possible
and keep
the size
the same
yet free
from the
need for
hyphena-
Dammit!! (Matthew Winn)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202010081917.098JHjAS3275508%40masaka.moolenaar.net.