aptos-core icon indicating copy to clipboard operation
aptos-core copied to clipboard

[Bug][compiler-v2] Bytecode verification error when multiple mutable references are used in a particular order

Open vineethk opened this issue 1 year ago • 1 comments

🐛 Bug

Consider the following program:

    public fun test1(): u64 {
        let x = 0;
        let r1 = &mut x;
        let r2 = &mut x;
        *r1 + *r2
    }

    public fun test2(): u64 {
        let x = 0;
        let r1 = &mut x;
        let r2 = &mut x;
        *r2 + *r1 // <- changed order here
    }

v1 and v2 compiler and run test1 without any issues, but on test2:

  • v1 gives a compiler error
  • v2 does not give a normal compiler error but gives a "bytecode verification failure bug" error due to READREF_EXISTS_MUTABLE_BORROW_ERROR. We should instead provide a proper compiler error.

There are similar variations of the same problem:

    public fun test3() {
        let x = 0;
        let r1 = &mut x;
        let r2 = &mut x;
        let _ = *r1;
        let _ = *r2;
    }

    public fun test4() {
        let x = 0;
        let r1 = &mut x;
        let r2 = &mut x;
        let _ = *r2; // <- order changed
        let _ = *r1; // <-
    }

v1 and v2 compiler and run test3 without any issues, but on test4:

  • v1 gives a compiler error
  • v2 does not give a normal compiler error but gives a "bytecode verification failure bug" error due to READREF_EXISTS_MUTABLE_BORROW_ERROR.

vineethk avatar Apr 06 '24 00:04 vineethk

@brmataptos asked for the generated bytecode, so here it is for the first pair:

public test1(): u64 /* def_idx: 0 */ {
L0:     loc0: u64
L1:     loc1: &mut u64
L2:     loc2: &mut u64
B0:
        0: LdU64(0)
        1: StLoc[0](loc0: u64)
        2: MutBorrowLoc[0](loc0: u64)
        3: MutBorrowLoc[0](loc0: u64)
        4: StLoc[1](loc1: &mut u64)
        5: StLoc[2](loc2: &mut u64)
        6: MoveLoc[2](loc2: &mut u64)
        7: ReadRef
        8: MoveLoc[1](loc1: &mut u64)
        9: ReadRef
        10: Add
        11: Ret
}
public test2(): u64 /* def_idx: 0 */ {
L0:     loc0: u64
L1:     loc1: u64
L2:     loc2: &mut u64
L3:     loc3: u64
B0:
        0: LdU64(0)
        1: StLoc[0](loc0: u64)
        2: MutBorrowLoc[0](loc0: u64)
        3: MutBorrowLoc[0](loc0: u64)
        4: ReadRef
        5: StLoc[1](loc1: u64)
        6: StLoc[2](loc2: &mut u64)
        7: MoveLoc[2](loc2: &mut u64)
        8: ReadRef
        9: StLoc[3](loc3: u64)
        10: MoveLoc[1](loc1: u64)
        11: MoveLoc[3](loc3: u64)
        12: Add
        13: Ret
}

vineethk avatar Apr 06 '24 01:04 vineethk

Mitigated by #13469 so downgrading priority to medium

wrwg avatar May 30 '24 20:05 wrwg