Wilfred / bfc

An industrial-grade brainfuck compiler
https://bfc.wilfred.me.uk
GNU General Public License v2.0
508 stars 31 forks source link

Soundness failure #12

Closed Wilfred closed 8 years ago

Wilfred commented 8 years ago

In #11 we saw a soundness test failure in quickcheck on Travis. This is clearly a bug that quickcheck rarely finds. We should identify and fix it.

Wilfred commented 8 years ago

The failing test was combine_before_read_is_sound, the placeholder value was Some(0), and the program was:

[PointerIncrement { amount: 82, position: Some(Position { start: 0, end: 0 }) }, Increment { amount: Wrapping(-28), offset: 0, position: Some(Position { start: 0, end: 0 }) }, MultiplyMove { changes: {1: Wrapping(-1)}, position: Some(Position { start: 0, end: 0 }) }, Read { position: Some(Position { start: 0, end: 0 }) }, PointerIncrement { amount: 72, position: Some(Position { start: 0, end: 0 }) }, PointerIncrement { amount: -77, position: Some(Position { start: 0, end: 0 }) }, PointerIncrement { amount: -24, position: Some(Position { start: 0, end: 0 }) }, PointerIncrement { amount: 30, position: Some(Position { start: 0, end: 0 }) }, Loop { body: [Write { position: Some(Position { start: 0, end: 0 }) }, PointerIncrement { amount: 19, position: Some(Position { start: 0, end: 0 }) }, Set { amount: Wrapping(23), offset: 0, position: Some(Position { start: 0, end: 0 }) }, Read { position: Some(Position { start: 0, end: 0 }) }], position: Some(Position { start: 0, end: 0 }) }]
Wilfred commented 8 years ago

Oddly, the test on Traivs failed with 'Different outputs!', whereas my quick and dirty failing test is giving 'Optimised program did not terminate properly':

#[test]
fn combine_before_read_sound_foo() {
    let mut changes = HashMap::new();
    changes.insert(1, Wrapping(-1));
    let instrs = vec![PointerIncrement { amount: 82, position: Some(Position { start: 0, end: 0 }) },
                  Increment { amount: Wrapping(-28), offset: 0, position: Some(Position { start: 0, end: 0 }) },
                  MultiplyMove { changes: changes, position: Some(Position { start: 0, end: 0 }) },
                  Read { position: Some(Position { start: 0, end: 0 }) },
                  PointerIncrement { amount: 72, position: Some(Position { start: 0, end: 0 }) },
                  PointerIncrement { amount: -77, position: Some(Position { start: 0, end: 0 }) },
                  PointerIncrement { amount: -24, position: Some(Position { start: 0, end: 0 }) },
                  PointerIncrement { amount: 30, position: Some(Position { start: 0, end: 0 }) },
                  Loop { body:
                         vec![Write { position: Some(Position { start: 0, end: 0 }) },
                              PointerIncrement { amount: 19, position: Some(Position { start: 0, end: 0 }) },
                              Set { amount: Wrapping(23), offset: 0, position: Some(Position { start: 0, end: 0 }) },
                              Read { position: Some(Position { start: 0, end: 0 }) }],
                         position: Some(Position { start: 0, end: 0 }) }];

    assert!(!transform_is_sound(instrs, combine_before_read, false, Some(0)).is_failure());
}
Wilfred commented 8 years ago

The build in question was job #55 and I've attached the log in case Travis discards old logs.

log.txt