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)
diff --git a/src/eval.c b/src/eval.c
index 40c6feb..3e316bd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,16 +57,21 @@
/*
* 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 @@
/*
* 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 @@
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 @@
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 @@
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 @@
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;