Skip to content

Commit dbb239d

Browse files
committed
Fix porting mistake found by fuzzing: -x should be x.wrapping_neg() to avoid overflow panics.
1 parent 4aca99d commit dbb239d

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ pub trait Float:
360360
fn from_bits(input: u128) -> Self;
361361
fn from_i128_r(input: i128, round: Round) -> StatusAnd<Self> {
362362
if input < 0 {
363-
Self::from_u128_r(-input as u128, -round).map(|r| -r)
363+
Self::from_u128_r(input.wrapping_neg() as u128, -round).map(|r| -r)
364364
} else {
365365
Self::from_u128_r(input as u128, round)
366366
}

tests/downstream.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! Tests added to `rustc_apfloat`, that were not ported from the C++ code.
2+
3+
use rustc_apfloat::ieee::{Double, Single};
4+
use rustc_apfloat::Float;
5+
6+
// `f32 -> i128 -> f32` previously-crashing bit-patterns (found by fuzzing).
7+
pub const FUZZ_IEEE32_ROUNDTRIP_THROUGH_I128_CASES: &[u32] = &[
8+
0xff000000, // -1.7014118e+38
9+
0xff00e203, // -1.713147e+38
10+
0xff00e900, // -1.7135099e+38
11+
0xff7fffff, // -3.4028235e+38
12+
0xff800000, // -inf
13+
];
14+
15+
// `f64 -> i128 -> f64` previously-crashing bit-patterns (found by fuzzing).
16+
pub const FUZZ_IEEE64_ROUNDTRIP_THROUGH_I128_CASES: &[u64] = &[
17+
0xc7e5d58020ffedff, // -2.3217876724230413e+38
18+
0xc7e7fffefefeff00, // -2.5521161229511617e+38
19+
0xc7e8030000653636, // -2.5533639056589687e+38
20+
0xea3501e2e8950007, // -4.116505897277026e+203
21+
0xf3ff0620ca000600, // -5.553072340247723e+250
22+
0xffc909842600d4ff, // -3.516340112093497e+307
23+
0xfff0000000000000, // -inf
24+
];
25+
26+
#[test]
27+
fn fuzz_roundtrip_through_i128() {
28+
for &bits in FUZZ_IEEE32_ROUNDTRIP_THROUGH_I128_CASES {
29+
assert_eq!(
30+
Single::from_i128(Single::from_bits(bits.into()).to_i128(128).value)
31+
.value
32+
.to_bits(),
33+
(f32::from_bits(bits) as i128 as f32).to_bits().into()
34+
);
35+
}
36+
for &bits in FUZZ_IEEE64_ROUNDTRIP_THROUGH_I128_CASES {
37+
assert_eq!(
38+
Double::from_i128(Double::from_bits(bits.into()).to_i128(128).value)
39+
.value
40+
.to_bits(),
41+
(f64::from_bits(bits) as i128 as f64).to_bits().into()
42+
);
43+
}
44+
}

0 commit comments

Comments
 (0)