summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-30 23:05:11 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-30 23:05:11 +0100
commitf2b26bcf8f498fed72759af4aa768fb2aab3118c (patch)
tree3fb840f0bd9de41b463443ddf17131a0ad77f226
parentb63f3ca66db20f7b135aae706d36be538f91f8cc (diff)
downloadvim-git-f2b26bcf8f498fed72759af4aa768fb2aab3118c.tar.gz
patch 8.2.2434: Vim9: no error when compiling str2nr() with a numberv8.2.2434
Problem: Vim9: no error when compiling str2nr() with a number. Solution: Add argument type checks. (closes #7759)
-rw-r--r--src/evalfunc.c17
-rw-r--r--src/proto/typval.pro2
-rw-r--r--src/testdir/test_vim9_builtin.vim7
-rw-r--r--src/typval.c24
-rw-r--r--src/version.c2
5 files changed, 50 insertions, 2 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index b752c51d1..1fad082ac 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -331,6 +331,18 @@ arg_string(type_T *type, argcontext_T *context)
}
/*
+ * Check "type" is a bool or number 0 or 1.
+ */
+ static int
+arg_bool(type_T *type, argcontext_T *context)
+{
+ if (type->tt_type == VAR_ANY
+ || type->tt_type == VAR_NUMBER || type->tt_type == VAR_BOOL)
+ return OK;
+ return check_arg_type(&t_bool, type, context);
+}
+
+/*
* Check "type" is a list or a blob.
*/
static int
@@ -423,6 +435,7 @@ arg_extend3(type_T *type, argcontext_T *context)
/*
* Lists of functions that check the argument types of a builtin function.
*/
+argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
@@ -1552,7 +1565,7 @@ static funcentry_T global_functions[] =
ret_float, FLOAT_FUNC(f_str2float)},
{"str2list", 1, 2, FEARG_1, NULL,
ret_list_number, f_str2list},
- {"str2nr", 1, 3, FEARG_1, NULL,
+ {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_str2nr},
{"strcharpart", 2, 3, FEARG_1, NULL,
ret_string, f_strcharpart},
@@ -9076,7 +9089,7 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
what |= STR2NR_QUOTE;
}
- p = skipwhite(tv_get_string(&argvars[0]));
+ p = skipwhite(tv_get_string_strict(&argvars[0]));
isneg = (*p == '-');
if (*p == '+' || *p == '-')
p = skipwhite(p + 1);
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index 7a65376c6..93eb64f4d 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -12,9 +12,11 @@ float_T tv_get_float(typval_T *varp);
int check_for_string(typval_T *tv);
int check_for_nonempty_string(typval_T *tv);
char_u *tv_get_string(typval_T *varp);
+char_u *tv_get_string_strict(typval_T *varp);
char_u *tv_get_string_buf(typval_T *varp, char_u *buf);
char_u *tv_get_string_chk(typval_T *varp);
char_u *tv_get_string_buf_chk(typval_T *varp, char_u *buf);
+char_u *tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict);
char_u *tv_stringify(typval_T *varp, char_u *buf);
int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
void copy_tv(typval_T *from, typval_T *to);
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 776aec0bd..292910016 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -867,6 +867,13 @@ enddef
def Test_str2nr()
str2nr("1'000'000", 10, true)->assert_equal(1000000)
+
+ CheckDefFailure(['echo str2nr(123)'], 'E1013:')
+ CheckScriptFailure(['vim9script', 'echo str2nr(123)'], 'E1024:')
+ CheckDefFailure(['echo str2nr("123", "x")'], 'E1013:')
+ CheckScriptFailure(['vim9script', 'echo str2nr("123", "x")'], 'E1030:')
+ CheckDefFailure(['echo str2nr("123", 10, "x")'], 'E1013:')
+ CheckScriptFailure(['vim9script', 'echo str2nr("123", 10, "x")'], 'E1135:')
enddef
def Test_strchars()
diff --git a/src/typval.c b/src/typval.c
index 7e4e63d17..b3325b663 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -388,6 +388,19 @@ tv_get_string(typval_T *varp)
return tv_get_string_buf(varp, mybuf);
}
+/*
+ * Like tv_get_string() but don't allow number to string conversion for Vim9.
+ */
+ char_u *
+tv_get_string_strict(typval_T *varp)
+{
+ static char_u mybuf[NUMBUFLEN];
+ char_u *res = tv_get_string_buf_chk_strict(
+ varp, mybuf, in_vim9script());
+
+ return res != NULL ? res : (char_u *)"";
+}
+
char_u *
tv_get_string_buf(typval_T *varp, char_u *buf)
{
@@ -410,9 +423,20 @@ tv_get_string_chk(typval_T *varp)
char_u *
tv_get_string_buf_chk(typval_T *varp, char_u *buf)
{
+ return tv_get_string_buf_chk_strict(varp, buf, FALSE);
+}
+
+ char_u *
+tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
+{
switch (varp->v_type)
{
case VAR_NUMBER:
+ if (strict)
+ {
+ emsg(_(e_using_number_as_string));
+ break;
+ }
vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
(varnumber_T)varp->vval.v_number);
return buf;
diff --git a/src/version.c b/src/version.c
index 555a2f937..8159289cb 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2434,
+/**/
2433,
/**/
2432,