Skip to content

Commit f2b26bc

Browse files
committed
patch 8.2.2434: Vim9: no error when compiling str2nr() with a number
Problem: Vim9: no error when compiling str2nr() with a number. Solution: Add argument type checks. (closes #7759)
1 parent b63f3ca commit f2b26bc

5 files changed

Lines changed: 50 additions & 2 deletions

File tree

src/evalfunc.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,18 @@ arg_string(type_T *type, argcontext_T *context)
330330
return check_arg_type(&t_string, type, context);
331331
}
332332

333+
/*
334+
* Check "type" is a bool or number 0 or 1.
335+
*/
336+
static int
337+
arg_bool(type_T *type, argcontext_T *context)
338+
{
339+
if (type->tt_type == VAR_ANY
340+
|| type->tt_type == VAR_NUMBER || type->tt_type == VAR_BOOL)
341+
return OK;
342+
return check_arg_type(&t_bool, type, context);
343+
}
344+
333345
/*
334346
* Check "type" is a list or a blob.
335347
*/
@@ -423,6 +435,7 @@ arg_extend3(type_T *type, argcontext_T *context)
423435
/*
424436
* Lists of functions that check the argument types of a builtin function.
425437
*/
438+
argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
426439
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
427440
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
428441
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
@@ -1552,7 +1565,7 @@ static funcentry_T global_functions[] =
15521565
ret_float, FLOAT_FUNC(f_str2float)},
15531566
{"str2list", 1, 2, FEARG_1, NULL,
15541567
ret_list_number, f_str2list},
1555-
{"str2nr", 1, 3, FEARG_1, NULL,
1568+
{"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool,
15561569
ret_number, f_str2nr},
15571570
{"strcharpart", 2, 3, FEARG_1, NULL,
15581571
ret_string, f_strcharpart},
@@ -9076,7 +9089,7 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
90769089
what |= STR2NR_QUOTE;
90779090
}
90789091

9079-
p = skipwhite(tv_get_string(&argvars[0]));
9092+
p = skipwhite(tv_get_string_strict(&argvars[0]));
90809093
isneg = (*p == '-');
90819094
if (*p == '+' || *p == '-')
90829095
p = skipwhite(p + 1);

src/proto/typval.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ float_T tv_get_float(typval_T *varp);
1212
int check_for_string(typval_T *tv);
1313
int check_for_nonempty_string(typval_T *tv);
1414
char_u *tv_get_string(typval_T *varp);
15+
char_u *tv_get_string_strict(typval_T *varp);
1516
char_u *tv_get_string_buf(typval_T *varp, char_u *buf);
1617
char_u *tv_get_string_chk(typval_T *varp);
1718
char_u *tv_get_string_buf_chk(typval_T *varp, char_u *buf);
19+
char_u *tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict);
1820
char_u *tv_stringify(typval_T *varp, char_u *buf);
1921
int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
2022
void copy_tv(typval_T *from, typval_T *to);

src/testdir/test_vim9_builtin.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,13 @@ enddef
867867

868868
def Test_str2nr()
869869
str2nr("1'000'000", 10, true)->assert_equal(1000000)
870+
871+
CheckDefFailure(['echo str2nr(123)'], 'E1013:')
872+
CheckScriptFailure(['vim9script', 'echo str2nr(123)'], 'E1024:')
873+
CheckDefFailure(['echo str2nr("123", "x")'], 'E1013:')
874+
CheckScriptFailure(['vim9script', 'echo str2nr("123", "x")'], 'E1030:')
875+
CheckDefFailure(['echo str2nr("123", 10, "x")'], 'E1013:')
876+
CheckScriptFailure(['vim9script', 'echo str2nr("123", 10, "x")'], 'E1135:')
870877
enddef
871878

872879
def Test_strchars()

src/typval.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,19 @@ tv_get_string(typval_T *varp)
388388
return tv_get_string_buf(varp, mybuf);
389389
}
390390

391+
/*
392+
* Like tv_get_string() but don't allow number to string conversion for Vim9.
393+
*/
394+
char_u *
395+
tv_get_string_strict(typval_T *varp)
396+
{
397+
static char_u mybuf[NUMBUFLEN];
398+
char_u *res = tv_get_string_buf_chk_strict(
399+
varp, mybuf, in_vim9script());
400+
401+
return res != NULL ? res : (char_u *)"";
402+
}
403+
391404
char_u *
392405
tv_get_string_buf(typval_T *varp, char_u *buf)
393406
{
@@ -409,10 +422,21 @@ tv_get_string_chk(typval_T *varp)
409422

410423
char_u *
411424
tv_get_string_buf_chk(typval_T *varp, char_u *buf)
425+
{
426+
return tv_get_string_buf_chk_strict(varp, buf, FALSE);
427+
}
428+
429+
char_u *
430+
tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
412431
{
413432
switch (varp->v_type)
414433
{
415434
case VAR_NUMBER:
435+
if (strict)
436+
{
437+
emsg(_(e_using_number_as_string));
438+
break;
439+
}
416440
vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
417441
(varnumber_T)varp->vval.v_number);
418442
return buf;

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2434,
753755
/**/
754756
2433,
755757
/**/

0 commit comments

Comments
 (0)