Repository: aptos-labs/aptos-core
File: third_party/move/move-vm/runtime/src/runtime_type_checks.rs (Rust)

Code before:
        ty_cache: &mut FrameTypeCache,
    ) -> PartialVMResult<()> {
        match instruction {
            // Call instruction will be checked at execute_main.
            Instruction::Call(_) | Instruction::CallGeneric(_) => (),
            Instruction::BrFalse(_) | Instruction::BrTrue(_) => {
                operand_stack.pop_ty()?;
            },
            Instruction::CallClosure(sig_idx) => {
                // For closure, we need to check the type of the closure on
                // top of the stack. The argument types are checked when the frame
                // is constructed in the interpreter, using the same code as for regular
                // calls.
                let (expected_ty, _) = ty_cache.get_signature_index_type(*sig_idx, frame)?;
                let given_ty = operand_stack.pop_ty()?;
                given_ty.paranoid_check_assignable(expected_ty)?;
            },
            Instruction::Branch(_) => (),
            Instruction::Ret => {
                frame.check_local_tys_have_drop_ability()?;
            },
            Instruction::Abort => {
                operand_stack.pop_ty()?;
            },
            Instruction::AbortMsg => {
                operand_stack.pop_ty()?;
                operand_stack.pop_ty()?;
            },
            // StLoc needs to check before execution as we need to check the drop ability of values.
            Instruction::StLoc(idx) => {
                let expected_ty = frame.local_ty_at(*idx as usize);
                let val_ty = operand_stack.pop_ty()?;
                // For store, use assignability
                val_ty.paranoid_check_assignable(expected_ty)?;
                if !frame.locals.is_invalid(*idx as usize)? {
                    expected_ty.paranoid_check_has_ability(Ability::Drop)?;
                }
            },
            // We will check the rest of the instructions after execution phase.
            Instruction::Pop
            | Instruction::LdU8(_)
            | Instruction::LdU16(_)
            | Instruction::LdU32(_)
            | Instruction::LdU64(_)
            | Instruction::LdU128(_)
            | Instruction::LdU256(_)
            | Instruction::LdI8(_)
            | Instruction::LdI16(_)
            | Instruction::LdI32(_)
            | Instruction::LdI64(_)
            | Instruction::LdI128(_)

Review comment (suggestion):
We should check types are expected (u64 and a reference to a vector of u8) - not sure why it has not been don for abort instruction above (that one needs to check the type is u64)

Code after:
        ty_cache: &mut FrameTypeCache,
    ) -> PartialVMResult<()> {
        match instruction {
            // Call instruction will be checked at execute_main.
            Instruction::Call(_) | Instruction::CallGeneric(_) => (),
            Instruction::BrFalse(_) | Instruction::BrTrue(_) => {
                operand_stack.pop_ty()?;
            },
            Instruction::CallClosure(sig_idx) => {
                // For closure, we need to check the type of the closure on
                // top of the stack. The argument types are checked when the frame
                // is constructed in the interpreter, using the same code as for regular
                // calls.
                let (expected_ty, _) = ty_cache.get_signature_index_type(*sig_idx, frame)?;
                let given_ty = operand_stack.pop_ty()?;
                given_ty.paranoid_check_assignable(expected_ty)?;
            },
            Instruction::Branch(_) => (),
            Instruction::Ret => {
                frame.check_local_tys_have_drop_ability()?;
            },
            Instruction::Abort => {
                let ty = operand_stack.pop_ty()?;
                ty.paranoid_check_is_u64_ty()?;
            },
            Instruction::AbortMsg => {
                let ty1 = operand_stack.pop_ty()?;
                ty1.paranoid_check_is_vec_ty(&Type::U8)?;
                let ty2 = operand_stack.pop_ty()?;
                ty2.paranoid_check_is_u64_ty()?;
            },
            // StLoc needs to check before execution as we need to check the drop ability of values.
            Instruction::StLoc(idx) => {
                let expected_ty = frame.local_ty_at(*idx as usize);
                let val_ty = operand_stack.pop_ty()?;
                // For store, use assignability
                val_ty.paranoid_check_assignable(expected_ty)?;
                if !frame.locals.is_invalid(*idx as usize)? {
                    expected_ty.paranoid_check_has_ability(Ability::Drop)?;
                }
            },
            // We will check the rest of the instructions after execution phase.
            Instruction::Pop
            | Instruction::LdU8(_)
            | Instruction::LdU16(_)
            | Instruction::LdU32(_)
            | Instruction::LdU64(_)
            | Instruction::LdU128(_)
            | Instruction::LdU256(_)
            | Instruction::LdI8(_)
            | Instruction::LdI16(_)