@@ -15,8 +15,11 @@ use crate::{
1515} ;
1616use malachite_bigint:: BigInt ;
1717use num_traits:: Zero ;
18- use rustpython_compiler_core:: OneIndexed ;
19- use rustpython_compiler_core:: bytecode:: PyCodeLocationInfoKind ;
18+ use rustpython_compiler_core:: {
19+ OneIndexed ,
20+ bytecode:: PyCodeLocationInfoKind ,
21+ marshal:: { MarshalError , parse_instructions_from_bytes} ,
22+ } ;
2023use std:: { borrow:: Borrow , fmt, ops:: Deref } ;
2124
2225/// State for iterating through code address ranges
@@ -454,11 +457,8 @@ impl Constructor for PyCode {
454457
455458 // Parse and validate bytecode from bytes
456459 let bytecode_bytes = args. co_code . as_bytes ( ) ;
457- let instructions = parse_bytecode ( bytecode_bytes) . ok_or_else ( || {
458- vm. new_value_error (
459- "bytecode must have even length and contain only valid opcodes" . to_owned ( ) ,
460- )
461- } ) ?;
460+ let instructions = parse_bytecode ( bytecode_bytes)
461+ . map_err ( |e| vm. new_value_error ( format ! ( "invalid bytecode: {}" , e) ) ) ?;
462462
463463 // Convert constants
464464 let constants: Box < [ Literal ] > = args
@@ -925,11 +925,8 @@ impl PyCode {
925925 let instructions = match co_code {
926926 OptionalArg :: Present ( code_bytes) => {
927927 // Parse and validate bytecode from bytes
928- parse_bytecode ( code_bytes. as_bytes ( ) ) . ok_or_else ( || {
929- vm. new_value_error (
930- "bytecode must have even length and contain only valid opcodes" . to_owned ( ) ,
931- )
932- } ) ?
928+ parse_bytecode ( code_bytes. as_bytes ( ) )
929+ . map_err ( |e| vm. new_value_error ( format ! ( "invalid bytecode: {}" , e) ) ) ?
933930 }
934931 OptionalArg :: Missing => self . code . instructions . clone ( ) ,
935932 } ;
@@ -1037,23 +1034,16 @@ impl ToPyObject for bytecode::CodeObject {
10371034}
10381035
10391036/// Validates and parses bytecode bytes into CodeUnit instructions.
1040- /// Returns None if bytecode is invalid (odd length or contains invalid opcodes).
1041- fn parse_bytecode ( bytecode_bytes : & [ u8 ] ) -> Option < Box < [ CodeUnit ] > > {
1037+ /// Returns MarshalError if bytecode is invalid (odd length or contains invalid opcodes).
1038+ /// Note: Returning MarshalError is not necessary at this point because this is not a part of marshalling API.
1039+ /// However, we (temporarily) reuse MarshalError for simplicity.
1040+ fn parse_bytecode ( bytecode_bytes : & [ u8 ] ) -> Result < Box < [ CodeUnit ] > , MarshalError > {
10421041 // Bytecode must have even length (each instruction is 2 bytes)
10431042 if !bytecode_bytes. len ( ) . is_multiple_of ( 2 ) {
1044- return None ;
1045- }
1046-
1047- let mut instructions = Vec :: with_capacity ( bytecode_bytes. len ( ) / 2 ) ;
1048-
1049- for chunk in bytecode_bytes. chunks_exact ( 2 ) {
1050- // Try to parse the opcode - if invalid, return None
1051- let op = rustpython_compiler_core:: bytecode:: Instruction :: try_from ( chunk[ 0 ] ) . ok ( ) ?;
1052- let arg = rustpython_compiler_core:: bytecode:: OpArgByte ( chunk[ 1 ] ) ;
1053- instructions. push ( CodeUnit { op, arg } ) ;
1043+ return Err ( MarshalError :: InvalidBytecode ) ;
10541044 }
10551045
1056- Some ( instructions . into_boxed_slice ( ) )
1046+ parse_instructions_from_bytes ( bytecode_bytes )
10571047}
10581048
10591049// Helper struct for reading linetable
0 commit comments