mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.2381: Vim9: divide by zero does not abort expression execution
Problem: Vim9: divide by zero does not abort expression execution. Solution: Use a "failed" flag. (issue #7704)
This commit is contained in:
31
src/eval.c
31
src/eval.c
@@ -57,16 +57,21 @@ static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *
|
||||
|
||||
/*
|
||||
* Return "n1" divided by "n2", taking care of dividing by zero.
|
||||
* If "failed" is not NULL set it to TRUE when dividing by zero fails.
|
||||
*/
|
||||
varnumber_T
|
||||
num_divide(varnumber_T n1, varnumber_T n2)
|
||||
num_divide(varnumber_T n1, varnumber_T n2, int *failed)
|
||||
{
|
||||
varnumber_T result;
|
||||
|
||||
if (n2 == 0)
|
||||
{
|
||||
if (in_vim9script())
|
||||
{
|
||||
emsg(_(e_divide_by_zero));
|
||||
if (failed != NULL)
|
||||
*failed = TRUE;
|
||||
}
|
||||
if (n1 == 0)
|
||||
result = VARNUM_MIN; // similar to NaN
|
||||
else if (n1 < 0)
|
||||
@@ -82,12 +87,17 @@ num_divide(varnumber_T n1, varnumber_T n2)
|
||||
|
||||
/*
|
||||
* Return "n1" modulus "n2", taking care of dividing by zero.
|
||||
* If "failed" is not NULL set it to TRUE when dividing by zero fails.
|
||||
*/
|
||||
varnumber_T
|
||||
num_modulus(varnumber_T n1, varnumber_T n2)
|
||||
num_modulus(varnumber_T n1, varnumber_T n2, int *failed)
|
||||
{
|
||||
if (n2 == 0 && in_vim9script())
|
||||
{
|
||||
emsg(_(e_divide_by_zero));
|
||||
if (failed != NULL)
|
||||
*failed = TRUE;
|
||||
}
|
||||
return (n2 == 0) ? 0 : (n1 % n2);
|
||||
}
|
||||
|
||||
@@ -1516,6 +1526,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||
varnumber_T n;
|
||||
char_u numbuf[NUMBUFLEN];
|
||||
char_u *s;
|
||||
int failed = FALSE;
|
||||
|
||||
// Can't do anything with a Funcref, Dict, v:true on the right.
|
||||
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
|
||||
@@ -1599,8 +1610,10 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||
case '+': n += tv_get_number(tv2); break;
|
||||
case '-': n -= tv_get_number(tv2); break;
|
||||
case '*': n *= tv_get_number(tv2); break;
|
||||
case '/': n = num_divide(n, tv_get_number(tv2)); break;
|
||||
case '%': n = num_modulus(n, tv_get_number(tv2)); break;
|
||||
case '/': n = num_divide(n, tv_get_number(tv2),
|
||||
&failed); break;
|
||||
case '%': n = num_modulus(n, tv_get_number(tv2),
|
||||
&failed); break;
|
||||
}
|
||||
clear_tv(tv1);
|
||||
tv1->v_type = VAR_NUMBER;
|
||||
@@ -1619,7 +1632,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||
tv1->v_type = VAR_STRING;
|
||||
tv1->vval.v_string = s;
|
||||
}
|
||||
return OK;
|
||||
return failed ? FAIL : OK;
|
||||
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
@@ -3196,12 +3209,16 @@ eval6(
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int failed = FALSE;
|
||||
|
||||
if (op == '*')
|
||||
n1 = n1 * n2;
|
||||
else if (op == '/')
|
||||
n1 = num_divide(n1, n2);
|
||||
n1 = num_divide(n1, n2, &failed);
|
||||
else
|
||||
n1 = num_modulus(n1, n2);
|
||||
n1 = num_modulus(n1, n2, &failed);
|
||||
if (failed)
|
||||
return FAIL;
|
||||
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
rettv->vval.v_number = n1;
|
||||
|
Reference in New Issue
Block a user