diff src/eval.c @ 23679:e8c379b20765 v8.2.2381

patch 8.2.2381: Vim9: divide by zero does not abort expression execution Commit: https://github.com/vim/vim/commit/c5f59fab23820454f060562927ddc1397f9d479a Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 21 12:34:14 2021 +0100 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 https://github.com/vim/vim/issues/7704)
author Bram Moolenaar <Bram@vim.org>
date Thu, 21 Jan 2021 12:45:05 +0100
parents 6d35bc0f161e
children a0c4d04a58c4
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,16 +57,21 @@ static char_u *make_expanded_name(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 n
 
 /*
  * 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
     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
 			    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
 		    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;