aptos-labs / aptos-core

Aptos is a layer 1 blockchain built to support the widespread use of blockchain through better technology and user experience.
https://aptosfoundation.org
Other
5.85k stars 3.54k forks source link

[Bug][Compiler-v2] incorrect type of an empty vector constant leads to STLOC_TYPE_MISMATCH_ERROR #13201

Closed rahxephon89 closed 1 week ago

rahxephon89 commented 2 weeks ago

🐛 Bug

When compiling the following code:

module 0x42::m {
    use std::bcs;
    use std::string::{Self};
    use std::vector;

    const KEYS: vector<vector<u8>> = vector[];
    const VALUES: vector<u64> = vector[];

    public entry fun init(
    ) {
        let _ = vector::map(KEYS, |key|{ string::utf8(key)});
        let _ = vector::map(VALUES, |v|{ bcs::to_bytes<u64>(&v)});
    }
}

The following error will be generated:

    ┌─ /aptos-core/third_party/move/move-compiler-v2/../move-stdlib/sources/vector.move:161:23
    │
161 │     public inline fun for_each<Element>(v: vector<Element>, f: |Element|) {
    │                       ^^^^^^^^ ICE failed bytecode verifier: VMError {
    major_status: STLOC_TYPE_MISMATCH_ERROR,
    sub_status: None,
    message: None,
    exec_state: None,
    location: Module(
        ModuleId {
            address: 0000000000000000000000000000000000000000000000000000000000000042,
            name: Identifier(
                "m",
            ),
        },
    ),
    indices: [
        (
            FunctionDefinition,
            0,
        ),
    ],
    offsets: [
        (
            FunctionDefinitionIndex(0),
            29,
        ),
    ],
}

However the error will not be generated if KEYS is replaced by vector[] in the code. Also, although the error is triggered by the second let statement but if the first let statement is remove, there will be no error.

rahxephon89 commented 2 weeks ago

Here is generated bytecode:

entry public init() /* def_idx: 0 */ {
L0: loc0: vector<String>
L1: loc1: vector<vector<u8>>
L2: loc2: vector<u8>
L3: loc3: vector<u8>
L4: loc4: vector<String>
L5: loc5: vector<String>
L6: loc6: vector<vector<u8>>
L7: loc7: vector<u64>
L8: loc8: u64
L9: loc9: u64
L10:    loc10: vector<vector<u8>>
L11:    loc11: vector<vector<u8>>
B0:
    0: VecPack(1, 0)
    1: StLoc[0](loc0: vector<String>)
    2: LdConst[0](Vector(Vector(U8)): [0])
    3: StLoc[1](loc1: vector<vector<u8>>)
    4: MutBorrowLoc[1](loc1: vector<vector<u8>>)
    5: Call vector::reverse<vector<u8>>(&mut vector<vector<u8>>)
B1:
    6: ImmBorrowLoc[1](loc1: vector<vector<u8>>)
    7: Call vector::is_empty<vector<u8>>(&vector<vector<u8>>): bool
    8: Not
    9: BrFalse(20)
B2:
    10: MutBorrowLoc[1](loc1: vector<vector<u8>>)
    11: VecPopBack(2)
    12: StLoc[2](loc2: vector<u8>)
    13: MutBorrowLoc[0](loc0: vector<String>)
    14: MoveLoc[2](loc2: vector<u8>)
    15: StLoc[3](loc3: vector<u8>)
    16: MoveLoc[3](loc3: vector<u8>)
    17: Call string::utf8(vector<u8>): String
    18: VecPushBack(1)
    19: Branch(21)
B3:
    20: Branch(22)
B4:
    21: Branch(6)
B5:
    22: MoveLoc[0](loc0: vector<String>)
    23: StLoc[4](loc4: vector<String>)
    24: MoveLoc[4](loc4: vector<String>)
    25: StLoc[5](loc5: vector<String>)
    26: VecPack(2, 0)
    27: StLoc[6](loc6: vector<vector<u8>>)
    28: LdConst[0](Vector(Vector(U8)): [0])
    29: StLoc[7](loc7: vector<u64>)
    30: MutBorrowLoc[7](loc7: vector<u64>)
    31: Call vector::reverse<u64>(&mut vector<u64>)
B6:
    32: ImmBorrowLoc[7](loc7: vector<u64>)
    33: Call vector::is_empty<u64>(&vector<u64>): bool
    34: Not
    35: BrFalse(46)
B7:
    36: MutBorrowLoc[7](loc7: vector<u64>)
    37: VecPopBack(6)
    38: StLoc[8](loc8: u64)
    39: MutBorrowLoc[6](loc6: vector<vector<u8>>)
    40: MoveLoc[8](loc8: u64)
    41: StLoc[9](loc9: u64)
    42: ImmBorrowLoc[9](loc9: u64)
    43: Call bcs::to_bytes<u64>(&u64): vector<u8>
    44: VecPushBack(2)
    45: Branch(47)
B8:
    46: Branch(48)
B9:
    47: Branch(32)
B10:
    48: MoveLoc[6](loc6: vector<vector<u8>>)
    49: StLoc[10](loc10: vector<vector<u8>>)
    50: MoveLoc[10](loc10: vector<vector<u8>>)
    51: StLoc[11](loc11: vector<vector<u8>>)
    52: Ret
}
}

The error happens at instr 28 and 29 where the type of vector is not correct.

rahxephon89 commented 2 weeks ago

The issue may be caused by two constants with different types but the same value:

const KEYS: vector<vector<u8>> = vector[];
const VALUES: vector<u64> = vector[];

cc @brianrmurphy