mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-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 vim/vim#4058)
e21c1580b7
This commit is contained in:
parent
98d389ce55
commit
b457a58e34
@ -526,6 +526,35 @@ const list_T *eval_msgpack_type_lists[] = {
|
||||
[kMPExt] = NULL,
|
||||
};
|
||||
|
||||
// Return "n1" divided by "n2", taking care of dividing by zero.
|
||||
varnumber_T num_divide(varnumber_T n1, varnumber_T n2)
|
||||
FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
varnumber_T result;
|
||||
|
||||
if (n2 == 0) { // give an error message?
|
||||
if (n1 == 0) {
|
||||
result = VARNUMBER_MIN; // similar to NaN
|
||||
} else if (n1 < 0) {
|
||||
result = -VARNUMBER_MAX;
|
||||
} else {
|
||||
result = VARNUMBER_MAX;
|
||||
}
|
||||
} else {
|
||||
result = n1 / n2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return "n1" modulus "n2", taking care of dividing by zero.
|
||||
varnumber_T num_modulus(varnumber_T n1, varnumber_T n2)
|
||||
FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
// Give an error when n2 is 0?
|
||||
return (n2 == 0) ? 0 : (n1 % n2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the global and v: variables.
|
||||
*/
|
||||
@ -2047,8 +2076,8 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||
case '+': n = numval + n; break;
|
||||
case '-': n = numval - n; break;
|
||||
case '*': n = numval * n; break;
|
||||
case '/': n = numval / n; break;
|
||||
case '%': n = numval % n; break;
|
||||
case '/': n = num_divide(numval, n); break;
|
||||
case '%': n = num_modulus(numval, n); break;
|
||||
}
|
||||
} else if (opt_type == 0 && stringval != NULL) { // string
|
||||
char *const oldstringval = stringval;
|
||||
@ -4178,22 +4207,9 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
|
||||
if (op == '*') {
|
||||
n1 = n1 * n2;
|
||||
} else if (op == '/') {
|
||||
if (n2 == 0) { // give an error message?
|
||||
if (n1 == 0) {
|
||||
n1 = VARNUMBER_MIN; // similar to NaN
|
||||
} else if (n1 < 0) {
|
||||
n1 = -VARNUMBER_MAX;
|
||||
n1 = num_divide(n1, n2);
|
||||
} else {
|
||||
n1 = VARNUMBER_MAX;
|
||||
}
|
||||
} else {
|
||||
n1 = n1 / n2;
|
||||
}
|
||||
} else {
|
||||
if (n2 == 0) /* give an error message? */
|
||||
n1 = 0;
|
||||
else
|
||||
n1 = n1 % n2;
|
||||
n1 = num_modulus(n1, n2);
|
||||
}
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
rettv->vval.v_number = n1;
|
||||
|
@ -74,8 +74,8 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
|
||||
case '+': n += tv_get_number(tv2); break;
|
||||
case '-': n -= tv_get_number(tv2); break;
|
||||
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;
|
||||
}
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_NUMBER;
|
||||
|
@ -21,7 +21,7 @@ com! -nargs=1 Xout call Xout(<args>)
|
||||
"
|
||||
" Create a script that consists of the body of the function a:funcname.
|
||||
" Replace any ":return" by a ":finish", any argument variable by a global
|
||||
" variable, and and every ":call" by a ":source" for the next following argument
|
||||
" variable, and every ":call" by a ":source" for the next following argument
|
||||
" in the variable argument list. This function is useful if similar tests are
|
||||
" to be made for a ":return" from a function call or a ":finish" in a script
|
||||
" file.
|
||||
@ -1310,6 +1310,43 @@ func Test_compound_assignment_operators()
|
||||
let x .= 'n'
|
||||
call assert_equal('2n', x)
|
||||
|
||||
" Test special cases: division or modulus with 0.
|
||||
let x = 1
|
||||
let x /= 0
|
||||
if has('num64')
|
||||
call assert_equal(0x7FFFFFFFFFFFFFFF, x)
|
||||
else
|
||||
call assert_equal(0x7fffffff, x)
|
||||
endif
|
||||
|
||||
let x = -1
|
||||
let x /= 0
|
||||
if has('num64')
|
||||
call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
|
||||
else
|
||||
call assert_equal(-0x7fffffff, x)
|
||||
endif
|
||||
|
||||
let x = 0
|
||||
let x /= 0
|
||||
if has('num64')
|
||||
call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
|
||||
else
|
||||
call assert_equal(-0x7FFFFFFF - 1, x)
|
||||
endif
|
||||
|
||||
let x = 1
|
||||
let x %= 0
|
||||
call assert_equal(0, x)
|
||||
|
||||
let x = -1
|
||||
let x %= 0
|
||||
call assert_equal(0, x)
|
||||
|
||||
let x = 0
|
||||
let x %= 0
|
||||
call assert_equal(0, x)
|
||||
|
||||
" Test for string
|
||||
let x = 'str'
|
||||
let x .= 'ing'
|
||||
|
Loading…
Reference in New Issue
Block a user