From 0f037e9a64986f74cddabfd20aa20a9f0afc3f89 Mon Sep 17 00:00:00 2001 From: Igor null Date: Tue, 2 Jul 2019 16:48:59 +0300 Subject: [PATCH] Fixed a few int overflows rem_pio2 had incorrect u32/i32 operations remquo has a straight int overflow --- src/math/rem_pio2.rs | 53 ++++++++++++++++++++++++-------------- src/math/rem_pio2_large.rs | 2 +- src/math/remquo.rs | 14 +++++++++- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/math/rem_pio2.rs b/src/math/rem_pio2.rs index 536dfac..dc6b329 100644 --- a/src/math/rem_pio2.rs +++ b/src/math/rem_pio2.rs @@ -179,29 +179,44 @@ pub(crate) fn rem_pio2(x: f64) -> (i32, f64, f64) { i -= 1; } let mut ty = [0.0; 3]; - let n = rem_pio2_large(&tx[..=i], &mut ty, ((ix >> 20) - (0x3ff + 23)) as i32, 1); + let n = rem_pio2_large(&tx[..=i], &mut ty, ((ix as i32) >> 20) - (0x3ff + 23), 1); if sign != 0 { return (-n, -ty[0], -ty[1]); } (n, ty[0], ty[1]) } -#[test] -fn test_near_pi() { - assert_eq!( - rem_pio2(3.141592025756836), - (2, -6.278329573009626e-7, -2.1125998133974653e-23) - ); - assert_eq!( - rem_pio2(3.141592033207416), - (2, -6.20382377148128e-7, -2.1125998133974653e-23) - ); - assert_eq!( - rem_pio2(3.141592144966125), - (2, -5.086236681942706e-7, -2.1125998133974653e-23) - ); - assert_eq!( - rem_pio2(3.141592979431152), - (2, 3.2584135866119817e-7, -2.1125998133974653e-23) - ); +#[cfg(test)] +mod tests { + use super::rem_pio2; + + #[test] + fn test_near_pi() { + assert_eq!( + rem_pio2(3.141592025756836), + (2, -6.278329573009626e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592033207416), + (2, -6.20382377148128e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592144966125), + (2, -5.086236681942706e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592979431152), + (2, 3.2584135866119817e-7, -2.1125998133974653e-23) + ); + } + + #[test] + fn test_overflow_b9b847() { + let _ = rem_pio2(-3054214.5490637687); + } + + #[test] + fn test_overflow_4747b9() { + let _ = rem_pio2(917340800458.2274); + } } diff --git a/src/math/rem_pio2_large.rs b/src/math/rem_pio2_large.rs index 006d3e1..5336a97 100644 --- a/src/math/rem_pio2_large.rs +++ b/src/math/rem_pio2_large.rs @@ -256,7 +256,7 @@ pub(crate) fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) -> let jv = jv as usize; /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ - let mut j = (jv - jx) as i32; + let mut j = (jv as i32) - (jx as i32); let m = jx + jk; for i in 0..=m { i!(f, i, =, if j < 0 { diff --git a/src/math/remquo.rs b/src/math/remquo.rs index 1c2ba89..c72c8f1 100644 --- a/src/math/remquo.rs +++ b/src/math/remquo.rs @@ -85,7 +85,8 @@ pub fn remquo(mut x: f64, mut y: f64) -> (f64, i32) { } if ex == ey || (ex + 1 == ey && (2.0 * x > y || (2.0 * x == y && (q % 2) != 0))) { x -= y; - q += 1; + // TODO: this matches musl behavior, but it is incorrect + q = q.wrapping_add(1); } q &= 0x7fffffff; let quo = if sx ^ sy { -(q as i32) } else { q as i32 }; @@ -95,3 +96,14 @@ pub fn remquo(mut x: f64, mut y: f64) -> (f64, i32) { (x, quo) } } + +#[cfg(test)] +mod tests { + use super::remquo; + + #[test] + fn test_q_overflow() { + // 0xc000000000000001, 0x04c0000000000004 + let _ = remquo(-2.0000000000000004, 8.406091369059082e-286); + } +}