ejmahler / RustFFT

RustFFT is a high-performance FFT library written in pure Rust.
Apache License 2.0
678 stars 47 forks source link

Initial attempt at roundtrip fuzzing #111

Closed Shnatsel closed 1 year ago

Shnatsel commented 1 year ago

This found a counter-example very quickly, but I suspect I'm just doing something wrong:

thread '<unnamed>' panicked at 'assertion failed: `float_eq!(left, right, rmax <= t)`
        left: `-6308.5176`,
       right: `NaN`,
    abs_diff: `NaN`,
   ulps_diff: `None`,
    [rmax] t: `630.85175`', fuzz_targets/roundtrip.rs:44:9
Shnatsel commented 1 year ago

You can run this with cargo +nightly fuzz run roundtrip

HEnquist commented 1 year ago

Roundtripping won't work when there are NaNs or infinity in the input data! If there is a NaN in the input, then every math operation involving that element will return NaN. Which basically means the entire output is just NaNs.

Shnatsel commented 1 year ago

I've added code that strips NaN and inf values from the input. The fuzzer still finds counter-examples very quickly.

Shnatsel commented 1 year ago

Okay, so either I'm doing something very wrong, or this is a bug:

thread '<unnamed>' panicked at 'assertion failed: `float_eq!(left, right, rmax <= t)`
        left: `-6328.63`,
       right: `2209923.3`,
    abs_diff: `2216252.0`,
   ulps_diff: `None`,
    [rmax] t: `2209923.3`', fuzz_targets/roundtrip.rs:51:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Input triggering it, text form:

    [
        -6328.63,
        1.9044803e-32,
        3310146.5,
        -2.6888979e38,
        3325951.8,
        -1.0587911e-22,
    ]

Binary form (gzipped):

crash-fcf909c931e12fec5df36a5e4d7f5a026663e4d6.gz

Reproduce with:

cargo fuzz run -O roundtrip crash-fcf909c931e12fec5df36a5e4d7f5a026663e4d6

HEnquist commented 1 year ago

That is just unavoidable numerical noise. With f32 you have roughly 8 significant digits. The values here: -6328.63, 1.9044803e-32, 3310146.5, -2.6888979e38, 3325951.8, -1.0587911e-22 have a range of 10^70! Since the largest term is at 10^38, you can get rounding errors up to 10^30. I don't think there is any point in testing with such a large range of values, the results will mostly be noise.

Shnatsel commented 1 year ago

All right, since roundtripping is harder than I thought it would be, I'll shelve it for now and focus on more traditional fuzzing that looks for memory errors.

Once the template is in place, someone with FFT domain knowledge can expand on that and implement comparisons against a reference implementation, roundtrips, etc.