]> granicus.if.org Git - vim/commitdiff
patch 8.2.2434: Vim9: no error when compiling str2nr() with a number v8.2.2434
authorBram Moolenaar <Bram@vim.org>
Sat, 30 Jan 2021 22:05:11 +0000 (23:05 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 30 Jan 2021 22:05:11 +0000 (23:05 +0100)
Problem:    Vim9: no error when compiling str2nr() with a number.
Solution:   Add argument type checks. (closes #7759)

src/evalfunc.c
src/proto/typval.pro
src/testdir/test_vim9_builtin.vim
src/typval.c
src/version.c

index b752c51d10d2d2c56ebf74f12df9474faed3af17..1fad082ac021834dd8b644cf9b8bf104da3307a7 100644 (file)
@@ -330,6 +330,18 @@ arg_string(type_T *type, argcontext_T *context)
     return check_arg_type(&t_string, type, 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.
  */
@@ -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);
index 7a65376c6e557d352d56fb415dea3aa600361949..93eb64f4d304dcf4e77e6500dbf360c13414a9ee 100644 (file)
@@ -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);
index 776aec0bdedd4916b5d7bf35d103d87c54fe3436..292910016230e6f4f74af906d864ac6149340acc 100644 (file)
@@ -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()
index 7e4e63d17dd8305b393971c9ef2a634cb83d3983..b3325b663aaa1bb27bc7f028fcdb4a5af465e231 100644 (file)
@@ -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)
 {
@@ -409,10 +422,21 @@ 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;
index 555a2f93785a26e186bccc8c8dc2472812d6e74d..8159289cb26e4746c9ffdfdd1bfb9a739369a988 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2434,
 /**/
     2433,
 /**/