comparison src/eval.c @ 15969:9cc42db77a54 v8.1.0990

patch 8.1.0990: floating point exception with "%= 0" and "/= 0" commit https://github.com/vim/vim/commit/e21c1580b7acb598a6e3c38565434fe5d0e2ad7a Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 2 11:57:09 2019 +0100 patch 8.1.0990: floating point exception with "%= 0" and "/= 0" Problem: Floating point exception with "%= 0" and "/= 0". Solution: Avoid dividing by zero. (Dominique Pelle, closes https://github.com/vim/vim/issues/4058)
author Bram Moolenaar <Bram@vim.org>
date Sat, 02 Mar 2019 12:00:06 +0100
parents fec4416adb80
children 93b08b92a049
comparison
equal deleted inserted replaced
15968:867ac4696428 15969:9cc42db77a54
251 static char_u *find_option_end(char_u **arg, int *opt_flags); 251 static char_u *find_option_end(char_u **arg, int *opt_flags);
252 252
253 /* for VIM_VERSION_ defines */ 253 /* for VIM_VERSION_ defines */
254 #include "version.h" 254 #include "version.h"
255 255
256 /*
257 * Return "n1" divided by "n2", taking care of dividing by zero.
258 */
259 static varnumber_T
260 num_divide(varnumber_T n1, varnumber_T n2)
261 {
262 varnumber_T result;
263
264 if (n2 == 0) // give an error message?
265 {
266 if (n1 == 0)
267 result = VARNUM_MIN; // similar to NaN
268 else if (n1 < 0)
269 result = -VARNUM_MAX;
270 else
271 result = VARNUM_MAX;
272 }
273 else
274 result = n1 / n2;
275
276 return result;
277 }
278
279 /*
280 * Return "n1" modulus "n2", taking care of dividing by zero.
281 */
282 static varnumber_T
283 num_modulus(varnumber_T n1, varnumber_T n2)
284 {
285 // Give an error when n2 is 0?
286 return (n2 == 0) ? 0 : (n1 % n2);
287 }
288
256 289
257 #if defined(EBCDIC) || defined(PROTO) 290 #if defined(EBCDIC) || defined(PROTO)
258 /* 291 /*
259 * Compare struct fst by function name. 292 * Compare struct fst by function name.
260 */ 293 */
1756 switch (*op) 1789 switch (*op)
1757 { 1790 {
1758 case '+': n = numval + n; break; 1791 case '+': n = numval + n; break;
1759 case '-': n = numval - n; break; 1792 case '-': n = numval - n; break;
1760 case '*': n = numval * n; break; 1793 case '*': n = numval * n; break;
1761 case '/': n = numval / n; break; 1794 case '/': n = (long)num_divide(numval, n); break;
1762 case '%': n = numval % n; break; 1795 case '%': n = (long)num_modulus(numval, n); break;
1763 } 1796 }
1764 } 1797 }
1765 else if (opt_type == 0 && stringval != NULL) // string 1798 else if (opt_type == 0 && stringval != NULL) // string
1766 { 1799 {
1767 s = concat_str(stringval, s); 1800 s = concat_str(stringval, s);
2536 switch (*op) 2569 switch (*op)
2537 { 2570 {
2538 case '+': n += tv_get_number(tv2); break; 2571 case '+': n += tv_get_number(tv2); break;
2539 case '-': n -= tv_get_number(tv2); break; 2572 case '-': n -= tv_get_number(tv2); break;
2540 case '*': n *= tv_get_number(tv2); break; 2573 case '*': n *= tv_get_number(tv2); break;
2541 case '/': n /= tv_get_number(tv2); break; 2574 case '/': n = num_divide(n, tv_get_number(tv2)); break;
2542 case '%': n %= tv_get_number(tv2); break; 2575 case '%': n = num_modulus(n, tv_get_number(tv2)); break;
2543 } 2576 }
2544 clear_tv(tv1); 2577 clear_tv(tv1);
2545 tv1->v_type = VAR_NUMBER; 2578 tv1->v_type = VAR_NUMBER;
2546 tv1->vval.v_number = n; 2579 tv1->vval.v_number = n;
2547 } 2580 }
4111 #endif 4144 #endif
4112 { 4145 {
4113 if (op == '*') 4146 if (op == '*')
4114 n1 = n1 * n2; 4147 n1 = n1 * n2;
4115 else if (op == '/') 4148 else if (op == '/')
4116 { 4149 n1 = num_divide(n1, n2);
4117 if (n2 == 0) /* give an error message? */
4118 {
4119 if (n1 == 0)
4120 n1 = VARNUM_MIN; /* similar to NaN */
4121 else if (n1 < 0)
4122 n1 = -VARNUM_MAX;
4123 else
4124 n1 = VARNUM_MAX;
4125 }
4126 else
4127 n1 = n1 / n2;
4128 }
4129 else 4150 else
4130 { 4151 n1 = num_modulus(n1, n2);
4131 if (n2 == 0) /* give an error message? */ 4152
4132 n1 = 0;
4133 else
4134 n1 = n1 % n2;
4135 }
4136 rettv->v_type = VAR_NUMBER; 4153 rettv->v_type = VAR_NUMBER;
4137 rettv->vval.v_number = n1; 4154 rettv->vval.v_number = n1;
4138 } 4155 }
4139 } 4156 }
4140 } 4157 }