Mercurial > vim
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 } |