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,
|
[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.
|
* 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 = numval * n; break;
|
||||||
case '/': n = numval / n; break;
|
case '/': n = num_divide(numval, n); break;
|
||||||
case '%': n = numval % n; break;
|
case '%': n = num_modulus(numval, n); break;
|
||||||
}
|
}
|
||||||
} else if (opt_type == 0 && stringval != NULL) { // string
|
} else if (opt_type == 0 && stringval != NULL) { // string
|
||||||
char *const oldstringval = stringval;
|
char *const oldstringval = stringval;
|
||||||
@ -4178,22 +4207,9 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
|
|||||||
if (op == '*') {
|
if (op == '*') {
|
||||||
n1 = n1 * n2;
|
n1 = n1 * n2;
|
||||||
} else if (op == '/') {
|
} else if (op == '/') {
|
||||||
if (n2 == 0) { // give an error message?
|
n1 = num_divide(n1, n2);
|
||||||
if (n1 == 0) {
|
|
||||||
n1 = VARNUMBER_MIN; // similar to NaN
|
|
||||||
} else if (n1 < 0) {
|
|
||||||
n1 = -VARNUMBER_MAX;
|
|
||||||
} else {
|
|
||||||
n1 = VARNUMBER_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
n1 = n1 / n2;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (n2 == 0) /* give an error message? */
|
n1 = num_modulus(n1, n2);
|
||||||
n1 = 0;
|
|
||||||
else
|
|
||||||
n1 = n1 % n2;
|
|
||||||
}
|
}
|
||||||
rettv->v_type = VAR_NUMBER;
|
rettv->v_type = VAR_NUMBER;
|
||||||
rettv->vval.v_number = n1;
|
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 *= tv_get_number(tv2); break;
|
||||||
case '/': n /= tv_get_number(tv2); break;
|
case '/': n = num_divide(n, tv_get_number(tv2)); break;
|
||||||
case '%': n %= tv_get_number(tv2); break;
|
case '%': n = num_modulus(n, tv_get_number(tv2)); break;
|
||||||
}
|
}
|
||||||
tv_clear(tv1);
|
tv_clear(tv1);
|
||||||
tv1->v_type = VAR_NUMBER;
|
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.
|
" 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
|
" 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
|
" 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
|
" to be made for a ":return" from a function call or a ":finish" in a script
|
||||||
" file.
|
" file.
|
||||||
@ -1310,6 +1310,43 @@ func Test_compound_assignment_operators()
|
|||||||
let x .= 'n'
|
let x .= 'n'
|
||||||
call assert_equal('2n', x)
|
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
|
" Test for string
|
||||||
let x = 'str'
|
let x = 'str'
|
||||||
let x .= 'ing'
|
let x .= 'ing'
|
||||||
|
Loading…
Reference in New Issue
Block a user