Skip to content

Commit 8270711

Browse files
committed
Fix porting mistake found by fuzzing: mul_add(finite, finite, ±inf_or_nan) needs to ignore the finite multiplication.
1 parent dbb239d commit 8270711

File tree

2 files changed

+355
-1
lines changed

2 files changed

+355
-1
lines changed

src/ieee.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,18 @@ impl<S: Semantics> Float for IeeeFloat<S> {
830830
// extended-precision calculation.
831831
if !self.is_finite_non_zero() || !multiplicand.is_finite_non_zero() || !addend.is_finite() {
832832
let mut status;
833-
self = unpack!(status=, self.mul_r(multiplicand, round));
833+
if self.is_finite_non_zero() && multiplicand.is_finite_non_zero() {
834+
// HACK(eddyb) this corresponds to the case where the C++ code
835+
// (`multiplySpecials`) is effectively a noop: no multiplication
836+
// is actually performed, because we're really only here to handle
837+
// the "infinite/NaN `addend`" special-case, which needs to ignore
838+
// the "finite * finite" multiplication entirely, instead of letting
839+
// it e.g. overflow into infinity (and trample over `addend`).
840+
assert!(!addend.is_finite());
841+
status = Status::OK;
842+
} else {
843+
self = unpack!(status=, self.mul_r(multiplicand, round));
844+
}
834845

835846
// FS can only be Status::OK or Status::INVALID_OP. There is no more work
836847
// to do in the latter case. The IEEE-754R standard says it is

tests/downstream.rs

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,346 @@ fn fuzz_roundtrip_through_i128() {
4242
);
4343
}
4444
}
45+
46+
// `f32` FMA bit-patterns which used to produce the wrong output (found by fuzzing).
47+
pub const FUZZ_IEEE32_FMA_CASES_WITH_EXPECTED_OUTPUTS: &[((u32, u32, u32), u32)] = &[
48+
((0x00001000 /* 5.74e-42 */, 0x0000001a /* 3.6e-44 */, 0xffff1a00 /* NaN */), 0xffff1a00 /* NaN */),
49+
((0x000080aa /* 4.6156e-41 */, 0xaaff0000 /* -4.52971e-13 */, 0xff9e007f /* NaN */), 0xff9e007f /* NaN */),
50+
((0x0000843f /* 4.7441e-41 */, 0x0084ff80 /* 1.2213942e-38 */, 0xffff8000 /* NaN */), 0xffff8000 /* NaN */),
51+
((0x00009eaa /* 5.6918e-41 */, 0x201d7f1e /* 1.3340477e-19 */, 0xffff0001 /* NaN */), 0xffff0001 /* NaN */),
52+
((0x020400ff /* 9.698114e-38 */, 0x7f7f2200 /* 3.3912968e+38 */, 0xffffffff /* NaN */), 0xffffffff /* NaN */),
53+
((0x02060320 /* 9.845662e-38 */, 0x20002521 /* 1.0854307e-19 */, 0x7f800000 /* inf */), 0x7f800000 /* inf */),
54+
(
55+
(0x04000080 /* 1.5046557e-36 */, 0xff7fff00 /* -3.4027717e+38 */, 0xff800000 /* -inf */),
56+
0xff800000, /* -inf */
57+
),
58+
(
59+
(0x04007faa /* 1.5104948e-36 */, 0xff200000 /* -2.1267648e+38 */, 0xffff0000 /* NaN */),
60+
0xffff0000, /* NaN */
61+
),
62+
((0x1e0603ff /* 7.094727e-21 */, 0x00100000 /* 1.469368e-39 */, 0xffffff4f /* NaN */), 0xffffff4f /* NaN */),
63+
((0x200004aa /* 1.0843565e-19 */, 0x00202020 /* 2.95026e-39 */, 0x7fff00ff /* NaN */), 0x7fff00ff /* NaN */),
64+
(
65+
(0x20005eaa /* 1.0873343e-19 */, 0x9e9e9e3a /* -1.6794342e-20 */, 0xff9e009e /* NaN */),
66+
0xff9e009e, /* NaN */
67+
),
68+
((0x20007faa /* 1.0884262e-19 */, 0x9e00611e /* -6.796347e-21 */, 0x7faa0600 /* NaN */), 0x7faa0600 /* NaN */),
69+
(
70+
(0x20007faa /* 1.0884262e-19 */, 0xaa069e1e /* -1.1956449e-13 */, 0xffffecff /* NaN */),
71+
0xffffecff, /* NaN */
72+
),
73+
((0x20025eaa /* 1.104275e-19 */, 0x9e01033a /* -6.82987e-21 */, 0xff9e009e /* NaN */), 0xff9e009e /* NaN */),
74+
((0x3314f400 /* 3.4680852e-8 */, 0x00ff7903 /* 2.3461462e-38 */, 0xffffffdb /* NaN */), 0xffffffdb /* NaN */),
75+
((0x3314f400 /* 3.4680852e-8 */, 0x00ff7903 /* 2.3461462e-38 */, 0xfffffff6 /* NaN */), 0xfffffff6 /* NaN */),
76+
((0x3a218275 /* 0.0006161102 */, 0x3a3a3a3a /* 0.00071040133 */, 0x7f8a063a /* NaN */), 0x7f8a063a /* NaN */),
77+
((0x40000001 /* 2.0000002 */, 0xfefffffe /* -1.7014116e+38 */, 0xfffe40ff /* NaN */), 0xfffe40ff /* NaN */),
78+
((0x50007faa /* 8623401000 */, 0x000011fb /* 6.45e-42 */, 0xff800000 /* -inf */), 0xff800000 /* -inf */),
79+
((0x64007f8b /* 9.481495e+21 */, 0xfa9a8702 /* -4.01176e+35 */, 0xff820000 /* NaN */), 0xff820000 /* NaN */),
80+
((0x6a017faa /* 3.9138577e+25 */, 0x00000070 /* 1.57e-43 */, 0xff80db03 /* NaN */), 0xff80db03 /* NaN */),
81+
((0x6a017faa /* 3.9138577e+25 */, 0x00000070 /* 1.57e-43 */, 0xff80db23 /* NaN */), 0xff80db23 /* NaN */),
82+
(
83+
(0x6e000000 /* 9.9035203e+27 */, 0xdf008000 /* -9259401000000000000 */, 0x7f800000 /* inf */),
84+
0x7f800000, /* inf */
85+
),
86+
((0x7f7fff00 /* 3.4027717e+38 */, 0x02000080 /* 9.404098e-38 */, 0x7fc00000 /* NaN */), 0x7fc00000 /* NaN */),
87+
(
88+
(0xb3eb00ff /* -1.09432214e-7 */, 0x00ffefe2 /* 2.3504105e-38 */, 0xfffffee9 /* NaN */),
89+
0xfffffee9, /* NaN */
90+
),
91+
(
92+
(0xdf0603ff /* -9656842000000000000 */, 0x808000ff /* -1.1755301e-38 */, 0xff9b0000 /* NaN */),
93+
0xff9b0000, /* NaN */
94+
),
95+
(
96+
(
97+
0xf1001101, /* -634154200000000000000000000000 */
98+
0x7f400000, /* 255211780000000000000000000000000000000 */
99+
0x7f800000, /* inf */
100+
),
101+
0x7f800000, /* inf */
102+
),
103+
((0xf5000080 /* -1.6226175e+32 */, 0xc9ffff00 /* -2097120 */, 0xffff7fff /* NaN */), 0xffff7fff /* NaN */),
104+
(
105+
(0xf5ffffff /* -6.4903707e+32 */, 0xff000b09 /* -1.7019848e+38 */, 0xff800000 /* -inf */),
106+
0xff800000, /* -inf */
107+
),
108+
(
109+
(0xf70029e8 /* -2.5994686e+33 */, 0xf7ffff7f /* -1.0384514e+34 */, 0xffff7fff /* NaN */),
110+
0xffff7fff, /* NaN */
111+
),
112+
(
113+
(0xff007faa /* -1.7080405e+38 */, 0xd3fface5 /* -2196234700000 */, 0xffff7f00 /* NaN */),
114+
0xffff7f00, /* NaN */
115+
),
116+
(
117+
(0xff200000 /* -2.1267648e+38 */, 0xe380ffff /* -4.7592594e+21 */, 0xff800000 /* -inf */),
118+
0xff800000, /* -inf */
119+
),
120+
((0xff6d0000 /* -3.1502704e+38 */, 0xc12005ff /* -10.001464 */, 0xff800000 /* -inf */), 0xff800000 /* -inf */),
121+
];
122+
123+
// `f64` FMA bit-patterns which used to produce the wrong output (found by fuzzing).
124+
pub const FUZZ_IEEE64_FMA_CASES_WITH_EXPECTED_OUTPUTS: &[((u64, u64, u64), u64)] = &[
125+
(
126+
(
127+
0x000000000000001e, /* 1.5e-322 */
128+
0x00000000ffdf0000, /* 2.120927281e-314 */
129+
0xffffff8000000000, /* NaN */
130+
),
131+
0xffffff8000000000, /* NaN */
132+
),
133+
(
134+
(
135+
0x000000007fffffff, /* 1.060997895e-314 */
136+
0xff00000000200000, /* -5.486124071348364e+303 */
137+
0xfffd0000000000e9, /* NaN */
138+
),
139+
0xfffd0000000000e9, /* NaN */
140+
),
141+
(
142+
(
143+
0x0000020000e30000, /* 1.086469195027e-311 */
144+
0xff00000011000000, /* -5.48612441622957e+303 */
145+
0xfffd00000000e0e9, /* NaN */
146+
),
147+
0xfffd00000000e0e9, /* NaN */
148+
),
149+
(
150+
(
151+
0x0000040000006400, /* 2.1729237025965e-311 */
152+
0x000000e5ff000000, /* 4.88050742876e-312 */
153+
0xffffffe300000000, /* NaN */
154+
),
155+
0xffffffe300000000, /* NaN */
156+
),
157+
(
158+
(
159+
0x00006a0000000000, /* 5.75824777836336e-310 */
160+
0x005015000018f9f1, /* 3.5783707339010265e-307 */
161+
0x7fffffde00000000, /* NaN */
162+
),
163+
0x7fffffde00000000, /* NaN */
164+
),
165+
(
166+
(
167+
0x00007ffa01000373, /* 6.95208343930866e-310 */
168+
0x0005000000ff107f, /* 6.95335589042254e-309 */
169+
0xffffffff00000005, /* NaN */
170+
),
171+
0xffffffff00000005, /* NaN */
172+
),
173+
(
174+
(
175+
0x0000ff8000000000, /* 1.387955006954565e-309 */
176+
0x0000000001000000, /* 8.289046e-317 */
177+
0xfff0000000000000, /* -inf */
178+
),
179+
0xfff0000000000000, /* -inf */
180+
),
181+
(
182+
(
183+
0x0002a000f6290000, /* 3.650532203442106e-309 */
184+
0x400013fffd000000, /* 2.009765602648258 */
185+
0xfffdfe0000ff9aff, /* NaN */
186+
),
187+
0xfffdfe0000ff9aff, /* NaN */
188+
),
189+
(
190+
(
191+
0x0006000000001700, /* 8.344026969431096e-309 */
192+
0xd9000000da080000, /* -5.164503950933907e+120 */
193+
0xfffffee5000000fd, /* NaN */
194+
),
195+
0xfffffee5000000fd, /* NaN */
196+
),
197+
(
198+
(
199+
0x0006000040000013, /* 8.344032274391576e-309 */
200+
0xfafe036500061100, /* -2.7893890583525793e+284 */
201+
0xffff7fff00001011, /* NaN */
202+
),
203+
0xffff7fff00001011, /* NaN */
204+
),
205+
(
206+
(
207+
0x00f1000000640000, /* 3.873408578194326e-304 */
208+
0xffe6005e00000000, /* -1.2359946076651026e+308 */
209+
0xfffd007000000000, /* NaN */
210+
),
211+
0xfffd007000000000, /* NaN */
212+
),
213+
(
214+
(
215+
0x05203a0080ff0513, /* 5.456081264530354e-284 */
216+
0xf90000000000f7ff, /* -6.924462078599005e+274 */
217+
0xfff0000000000000, /* -inf */
218+
),
219+
0xfff0000000000000, /* -inf */
220+
),
221+
(
222+
(
223+
0x0540400001000513, /* 2.1855837639726535e-283 */
224+
0xee05130640000100, /* -9.522265158052987e+221 */
225+
0x7fff00001004fa01, /* NaN */
226+
),
227+
0x7fff00001004fa01, /* NaN */
228+
),
229+
(
230+
(
231+
0x0540400001000513, /* 2.1855837639726535e-283 */
232+
0xffd8000000000000, /* -6.741349255733685e+307 */
233+
0xfff0001000000000, /* NaN */
234+
),
235+
0xfff0001000000000, /* NaN */
236+
),
237+
(
238+
(
239+
0x054040000100e213, /* 2.1855837639996873e-283 */
240+
0xfbd8000000000000, /* -3.6544927542749997e+288 */
241+
0xfff0ff1000000000, /* NaN */
242+
),
243+
0xfff0ff1000000000, /* NaN */
244+
),
245+
(
246+
(
247+
0x060000000000ff04, /* 8.814425663530262e-280 */
248+
0x00000020ffff0606, /* 7.00258294846e-313 */
249+
0xffffffde00001300, /* NaN */
250+
),
251+
0xffffffde00001300, /* NaN */
252+
),
253+
(
254+
(
255+
0x1306400001000513, /* 5.042468007014986e-217 */
256+
0x00001004fa03ee05, /* 8.7022551317144e-311 */
257+
0xfffc80f7ffff7fff, /* NaN */
258+
),
259+
0xfffc80f7ffff7fff, /* NaN */
260+
),
261+
(
262+
(
263+
0x1306400001000513, /* 5.042468007014986e-217 */
264+
0xa5001004fa01ee05, /* -1.810368898568446e-130 */
265+
0xfffa80f7ff1b7fff, /* NaN */
266+
),
267+
0xfffa80f7ff1b7fff, /* NaN */
268+
),
269+
(
270+
(
271+
0x4006400005130100, /* 2.7812500378059895 */
272+
0x0000ff4000000000, /* 1.38659692964835e-309 */
273+
0x7fffffec4200044b, /* NaN */
274+
),
275+
0x7fffffec4200044b, /* NaN */
276+
),
277+
(
278+
(
279+
0x4100000001000000, /* 131072.00048828125 */
280+
0x0000fffffff00000, /* 1.390671156386347e-309 */
281+
0xfffffe00000040ff, /* NaN */
282+
),
283+
0xfffffe00000040ff, /* NaN */
284+
),
285+
(
286+
(
287+
0x7a7a7a7a7a7a0000, /* 9.61276249042562e+281 */
288+
0xff7a7a7a7a7a7a7a, /* -1.1621116772547446e+306 */
289+
0xfffd007000ef0000, /* NaN */
290+
),
291+
0xfffd007000ef0000, /* NaN */
292+
),
293+
(
294+
(
295+
0x7f000012007ff010, /* 5.4862182545686e+303 */
296+
0x7f0000120091f010, /* 5.486218256005604e+303 */
297+
0xfff0000000000000, /* -inf */
298+
),
299+
0xfff0000000000000, /* -inf */
300+
),
301+
(
302+
(
303+
0x7f0022000a8000f6, /* 5.531663399192155e+303 */
304+
0xff00ebfef0800300, /* -5.802213559159178e+303 */
305+
0x7ff0000000000000, /* inf */
306+
),
307+
0x7ff0000000000000, /* inf */
308+
),
309+
(
310+
(
311+
0x7f06400001000513, /* 7.62914130360521e+303 */
312+
0xff001004fb88f7ff, /* -5.507580309563204e+303 */
313+
0xfffa01ee0513ffff, /* NaN */
314+
),
315+
0xfffa01ee0513ffff, /* NaN */
316+
),
317+
(
318+
(
319+
0xbbbbbb7f01000513, /* -5.872565540268704e-21 */
320+
0x0100bbbbbbbbbbbb, /* 7.625298445452731e-304 */
321+
0xffffff4000004000, /* NaN */
322+
),
323+
0xffffff4000004000, /* NaN */
324+
),
325+
(
326+
(
327+
0xbc00000000400000, /* -1.0842021734952464e-19 */
328+
0x00bc000000004000, /* 3.987332354453194e-305 */
329+
0xfff0000000e20000, /* NaN */
330+
),
331+
0xfff0000000e20000, /* NaN */
332+
),
333+
(
334+
(
335+
0xddff000004000000, /* -6.048387862754913e+144 */
336+
0xff00000000000000, /* -5.486124068793689e+303 */
337+
0xffffff0000000000, /* NaN */
338+
),
339+
0xffffff0000000000, /* NaN */
340+
),
341+
(
342+
(
343+
0xe100051b060c0513, /* -1.759578741202065e+159 */
344+
0xfbfeee0513064110, /* -1.8838766970066999e+289 */
345+
0xffff7fdf00001004, /* NaN */
346+
),
347+
0xffff7fdf00001004, /* NaN */
348+
),
349+
(
350+
(
351+
0xf0000000007ff010, /* -3.1050361903821855e+231 */
352+
0x7f06010800180000, /* 7.54480183807128e+303 */
353+
0x7ff0000000000000, /* inf */
354+
),
355+
0x7ff0000000000000, /* inf */
356+
),
357+
(
358+
(
359+
0xf4ffff05021d7d12, /* -3.753309156386366e+255 */
360+
0xfd100000e8030000, /* -2.5546778042386733e+294 */
361+
0xfff0000000000000, /* -inf */
362+
),
363+
0xfff0000000000000, /* -inf */
364+
),
365+
(
366+
(
367+
0xff0000fff05f0001, /* -5.48746313513839e+303 */
368+
0xff0000fff0800000, /* -5.487463137772898e+303 */
369+
0xfff0000000000000, /* -inf */
370+
),
371+
0xfff0000000000000, /* -inf */
372+
),
373+
];
374+
375+
#[test]
376+
fn fuzz_fma_with_expected_outputs() {
377+
for &((a_bits, b_bits, c_bits), expected_bits) in FUZZ_IEEE32_FMA_CASES_WITH_EXPECTED_OUTPUTS {
378+
let (a, b, c) =
379+
(Single::from_bits(a_bits.into()), Single::from_bits(b_bits.into()), Single::from_bits(c_bits.into()));
380+
assert_eq!(a.mul_add(b, c).value.to_bits(), expected_bits.into());
381+
}
382+
for &((a_bits, b_bits, c_bits), expected_bits) in FUZZ_IEEE64_FMA_CASES_WITH_EXPECTED_OUTPUTS {
383+
let (a, b, c) =
384+
(Double::from_bits(a_bits.into()), Double::from_bits(b_bits.into()), Double::from_bits(c_bits.into()));
385+
assert_eq!(a.mul_add(b, c).value.to_bits(), expected_bits.into());
386+
}
387+
}

0 commit comments

Comments
 (0)