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

Code before:
                        interpreter.binop_rel(Value::ge)?;
                    },
                    Instruction::Abort => {
                        gas_meter.charge_simple_instr(S::Abort)?;
                        let error_code = interpreter.operand_stack.pop_as::<u64>()?;
                        if is_tracing_for!(TraceCategory::Abort(error_code)) {
                            let mut str = String::new();
                            interpreter.debug_print_stack_trace(
                                &mut str,
                                interpreter.loader.runtime_environment(),
                            )?;
                            eprintln!("trace abort({}): {}", error_code, str);
                        }
                        let error =
                            PartialVMError::new(StatusCode::ABORTED).with_sub_status(error_code);

                        // Before returning an abort error, ensure the instruction is recorded in
                        // the trace, so the trace is full.
                        trace_recorder.record_successful_instruction(instruction);
                        return Err(error);
                    },
                    Instruction::AbortMsg => {
                        gas_meter.charge_simple_instr(S::Abort)?;

                        let vec_ref = interpreter.operand_stack.pop_as::<VectorRef>()?;
                        let error_message = String::from_utf8(vec_ref.as_bytes_ref().to_owned())
                            .map_err(|err| {
                                PartialVMError::new_invariant_violation(format!(
                                    "Invalid UTF-8 string: {err}",
                                ))
                            })?;

                        let error_code = interpreter.operand_stack.pop_as::<u64>()?;

                        if is_tracing_for!(TraceCategory::Abort(error_code)) {
                            let mut str = String::new();
                            interpreter.debug_print_stack_trace(
                                &mut str,
                                interpreter.loader.runtime_environment(),
                            )?;
                            eprintln!(
                                "trace abort_msg({}, {}): {}",
                                error_code, error_message, str
                            );
                        }
                        let error = PartialVMError::new(StatusCode::ABORTED)
                            .with_sub_status(error_code)
                            .with_message(error_message);

                        // Before returning an abort error, ensure the instruction is recorded in
                        // the trace, so the trace is full.

Review comment (bug):
Btw, `as_bytes_ref` panics if the type is not `u8`, so if there is a bug in verifier this can crash - changing the function to return PartialVMResult + invariant violation seems better since this is cold path anyway?

Code after:
                    Instruction::Xor => {
                        gas_meter.charge_simple_instr(S::Xor)?;
                        interpreter.binop(Value::bit_xor)?;
                    },
                    Instruction::Shl => {
                        gas_meter.charge_simple_instr(S::Shl)?;
                        let rhs = interpreter.operand_stack.pop_as::<u8>()?;
                        let lhs = interpreter.operand_stack.pop()?;
                        interpreter.operand_stack.push(lhs.shl_checked(rhs)?)?;
                    },
                    Instruction::Shr => {
                        gas_meter.charge_simple_instr(S::Shr)?;
                        let rhs = interpreter.operand_stack.pop_as::<u8>()?;
                        let lhs = interpreter.operand_stack.pop()?;
                        interpreter.operand_stack.push(lhs.shr_checked(rhs)?)?;
                    },
                    Instruction::Or => {
                        gas_meter.charge_simple_instr(S::Or)?;
                        interpreter.binop_bool(|l, r| Ok(l || r))?;
                    },
                    Instruction::And => {
                        gas_meter.charge_simple_instr(S::And)?;
                        interpreter.binop_bool(|l, r| Ok(l && r))?;
                    },
                    Instruction::Lt => {
                        gas_meter.charge_simple_instr(S::Lt)?;
                        interpreter.binop_rel(Value::lt)?;
                    },
                    Instruction::Gt => {
                        gas_meter.charge_simple_instr(S::Gt)?;
                        interpreter.binop_rel(Value::gt)?;
                    },
                    Instruction::Le => {
                        gas_meter.charge_simple_instr(S::Le)?;
                        interpreter.binop_rel(Value::le)?;
                    },
                    Instruction::Ge => {
                        gas_meter.charge_simple_instr(S::Ge)?;
                        interpreter.binop_rel(Value::ge)?;
                    },
                    Instruction::Abort => {
                        gas_meter.charge_simple_instr(S::Abort)?;
                        let error_code = interpreter.operand_stack.pop_as::<u64>()?;
                        if is_tracing_for!(TraceCategory::Abort(error_code)) {
                            let mut str = String::new();
                            interpreter.debug_print_stack_trace(
                                &mut str,
                                interpreter.loader.runtime_environment(),
                            )?;
                            eprintln!("trace abort({}): {}", error_code, str);
                        }