@@ -793,67 +793,72 @@ impl<'b> ValidatingOperatorParser<'b> {
793793/// The resources parameter contains all needed data to validate the operators.
794794pub fn validate_function_body (
795795 bytes : & [ u8 ] ,
796+ offset : usize ,
796797 func_index : u32 ,
797798 resources : & dyn WasmModuleResources ,
798799 operator_config : Option < OperatorValidatorConfig > ,
799- ) -> bool {
800+ ) -> Result < ( ) > {
800801 let operator_config = operator_config. unwrap_or ( DEFAULT_OPERATOR_VALIDATOR_CONFIG ) ;
801- let function_body = FunctionBody :: new ( 0 , bytes) ;
802- let mut locals_reader = if let Ok ( r) = function_body. get_locals_reader ( ) {
803- r
804- } else {
805- return false ;
806- } ;
802+ let function_body = FunctionBody :: new ( offset, bytes) ;
803+ let mut locals_reader = function_body. get_locals_reader ( ) ?;
807804 let local_count = locals_reader. get_count ( ) as usize ;
808805 if local_count > MAX_WASM_FUNCTION_LOCALS {
809- return false ;
806+ Err ( BinaryReaderError {
807+ message : "locals exceed maximum" ,
808+ offset : locals_reader. original_position ( ) ,
809+ } ) ?;
810810 }
811811 let mut locals: Vec < ( u32 , Type ) > = Vec :: with_capacity ( local_count) ;
812812 let mut locals_total: usize = 0 ;
813813 for _ in 0 ..local_count {
814- let ( count, ty) = if let Ok ( r) = locals_reader. read ( ) {
815- r
816- } else {
817- return false ;
818- } ;
819- locals_total = if let Some ( r) = locals_total. checked_add ( count as usize ) {
820- r
821- } else {
822- return false ;
823- } ;
814+ let ( count, ty) = locals_reader. read ( ) ?;
815+ locals_total =
816+ locals_total
817+ . checked_add ( count as usize )
818+ . ok_or_else ( || BinaryReaderError {
819+ message : "locals overflow" ,
820+ offset : locals_reader. original_position ( ) ,
821+ } ) ?;
824822 if locals_total > MAX_WASM_FUNCTION_LOCALS {
825- return false ;
823+ Err ( BinaryReaderError {
824+ message : "locals exceed maximum" ,
825+ offset : locals_reader. original_position ( ) ,
826+ } ) ?;
826827 }
827828 locals. push ( ( count, ty) ) ;
828829 }
829- let operators_reader = if let Ok ( r) = function_body. get_operators_reader ( ) {
830- r
831- } else {
832- return false ;
833- } ;
830+ let operators_reader = function_body. get_operators_reader ( ) ?;
834831 let func_type_index = resources. func_type_indices ( ) [ func_index as usize ] ;
835832 let func_type = & resources. types ( ) [ func_type_index as usize ] ;
836833 let mut operator_validator = OperatorValidator :: new ( func_type, & locals, operator_config) ;
837834 let mut eof_found = false ;
838- for op in operators_reader . into_iter ( ) {
839- let op = match op {
840- Err ( _ ) => return false ,
841- Ok ( ref op ) => op ,
842- } ;
843- match operator_validator . process_operator ( op , resources ) {
844- Err ( _ ) => return false ,
845- Ok ( FunctionEnd :: Yes ) => {
835+ let mut last_op = 0 ;
836+ for item in operators_reader . into_iter_with_offsets ( ) {
837+ let ( ref op , offset ) = item? ;
838+ match operator_validator
839+ . process_operator ( op , resources )
840+ . map_err ( |message| BinaryReaderError { message , offset } ) ?
841+ {
842+ FunctionEnd :: Yes => {
846843 eof_found = true ;
847844 }
848- Ok ( FunctionEnd :: No ) => ( ) ,
845+ FunctionEnd :: No => {
846+ last_op = offset;
847+ }
849848 }
850849 }
851- eof_found
850+ if !eof_found {
851+ Err ( BinaryReaderError {
852+ message : "end of function not found" ,
853+ offset : last_op,
854+ } ) ?;
855+ }
856+ Ok ( ( ) )
852857}
853858
854859/// Test whether the given buffer contains a valid WebAssembly module,
855860/// analogous to WebAssembly.validate in the JS API.
856- pub fn validate ( bytes : & [ u8 ] , config : Option < ValidatingParserConfig > ) -> bool {
861+ pub fn validate ( bytes : & [ u8 ] , config : Option < ValidatingParserConfig > ) -> Result < ( ) > {
857862 let mut parser = ValidatingParser :: new ( bytes, config) ;
858863 let mut parser_input = None ;
859864 let mut func_ranges = Vec :: new ( ) ;
@@ -862,7 +867,7 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool {
862867 let state = parser. read_with_input ( next_input) ;
863868 match * state {
864869 ParserState :: EndWasm => break ,
865- ParserState :: Error ( _ ) => return false ,
870+ ParserState :: Error ( e ) => Err ( e ) ? ,
866871 ParserState :: BeginFunctionBody { range } => {
867872 parser_input = Some ( ParserInput :: SkipFunctionBody ) ;
868873 func_ranges. push ( range) ;
@@ -874,23 +879,19 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool {
874879 for ( i, range) in func_ranges. into_iter ( ) . enumerate ( ) {
875880 let function_body = range. slice ( bytes) ;
876881 let function_index = i as u32 + parser. func_imports_count ;
877- if ! validate_function_body (
882+ validate_function_body (
878883 function_body,
884+ range. start ,
879885 function_index,
880886 & parser. resources ,
881887 operator_config,
882- ) {
883- return false ;
884- }
888+ ) ?;
885889 }
886- true
890+ Ok ( ( ) )
887891}
888892
889893#[ test]
890894fn test_validate ( ) {
891- assert ! ( validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x1 , 0x0 , 0x0 , 0x0 ] , None ) ) ;
892- assert ! ( !validate(
893- & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x2 , 0x0 , 0x0 , 0x0 ] ,
894- None
895- ) ) ;
895+ assert ! ( validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x1 , 0x0 , 0x0 , 0x0 ] , None ) . is_ok( ) ) ;
896+ assert ! ( validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x2 , 0x0 , 0x0 , 0x0 ] , None ) . is_err( ) ) ;
896897}
0 commit comments