@@ -20,6 +20,7 @@ use wasm::RuntimeError;
2020use wasm:: TableType ;
2121use wasm:: TrapError ;
2222use wasm:: ValType ;
23+ use wasm:: ValidationError ;
2324use wast:: core:: WastArgCore ;
2425use wast:: core:: WastRetCore ;
2526use wast:: { QuoteWat , WastArg , WastDirective , WastRet , Wat } ;
@@ -53,7 +54,110 @@ pub fn error_to_wasm_testsuite_string(runtime_error: &RuntimeError) -> Result<St
5354 RuntimeError :: HostFunctionSignatureMismatch => Ok ( "host function signature mismatch" ) ,
5455 _ => Err ( WastError :: UnrepresentedRuntimeError ) ,
5556 }
56- . map ( ToOwned :: to_owned)
57+ . map ( str:: to_owned)
58+ }
59+
60+ pub fn validation_error_to_wasm_testsuite_string (
61+ validation_error : & ValidationError ,
62+ ) -> Result < String , WastError > {
63+ std:: panic:: catch_unwind ( || {
64+ match validation_error {
65+ // _ => Err(WastError::UnrepresentedValidationError(
66+ // validation_error.clone(),
67+ // )),
68+ ValidationError :: InvalidMagic => Ok ( "magic header not detected" ) ,
69+ ValidationError :: InvalidBinaryFormatVersion => Ok ( "unknown binary version" ) ,
70+ ValidationError :: Eof => todo ! ( ) ,
71+ ValidationError :: MalformedUtf8 ( _) => Ok ( "malformed UTF-8 encoding" ) ,
72+ ValidationError :: MalformedSectionTypeDiscriminator ( _) => Ok ( "malformed section id" ) ,
73+ ValidationError :: MalformedNumTypeDiscriminator ( _) => Ok ( "malformed number type" ) ,
74+ ValidationError :: MalformedVecTypeDiscriminator ( _) => Ok ( "malformed vector type" ) ,
75+ ValidationError :: MalformedFuncTypeDiscriminator ( _) => Ok ( "malformed function type" ) ,
76+ ValidationError :: MalformedRefTypeDiscriminator ( _) => Ok ( "malformed reference type" ) ,
77+ ValidationError :: MalformedValType => todo ! ( ) ,
78+ ValidationError :: MalformedExportDescDiscriminator ( _) => Ok ( "malformed export kind" ) ,
79+ ValidationError :: MalformedImportDescDiscriminator ( _) => Ok ( "malformed import kind" ) ,
80+ ValidationError :: MalformedLimitsDiscriminator ( _) => todo ! ( ) ,
81+ ValidationError :: MalformedLimitsMinLargerThanMax { .. } => todo ! ( ) ,
82+ ValidationError :: MalformedMutDiscriminator ( _) => Ok ( "malformed mutability" ) ,
83+ ValidationError :: MalformedVariableLengthInteger => todo ! ( ) ,
84+ ValidationError :: MalformedElemKindDiscriminator ( _) => Ok ( "malformed element kind" ) ,
85+ ValidationError :: InvalidTypeIdx ( _) => Ok ( "unknown type" ) ,
86+ ValidationError :: InvalidFuncIdx ( _) => Ok ( "unknown function" ) ,
87+ ValidationError :: InvalidTableIdx ( _) => Ok ( "unknown table" ) ,
88+ ValidationError :: InvalidMemIdx ( _) => Ok ( "unknown memory" ) ,
89+ ValidationError :: InvalidGlobalIdx ( _) => Ok ( "unknown global" ) ,
90+ ValidationError :: InvalidElemIdx ( _) => Ok ( "unknown elem segment" ) ,
91+ ValidationError :: InvalidDataIdx ( _) => Ok ( "unknown data segment" ) ,
92+ ValidationError :: InvalidLocalIdx ( _) => Ok ( "unknown local" ) ,
93+ ValidationError :: InvalidLabelIdx ( _) => Ok ( "unknown label" ) ,
94+ ValidationError :: InvalidLaneIdx ( _) => {
95+ todo ! ( "this can be \" malformed lane index\" or \" invalid lane index\" " )
96+ }
97+ ValidationError :: UnexpectedContentAfterLastSection => {
98+ Ok ( "unexpected content after last section" )
99+ }
100+ ValidationError :: InvalidCustomSectionLength => todo ! ( ) ,
101+ ValidationError :: ExprMissingEnd => todo ! ( ) ,
102+ ValidationError :: InvalidInstr ( byte) => return Ok ( format ! ( "illegal opcode {byte:02x}" ) ) ,
103+ ValidationError :: InvalidMultiByteInstr ( byte, i) => {
104+ return Ok ( format ! ( "illegal opcode {byte:02x} {i:02x}" ) )
105+ }
106+ ValidationError :: EndInvalidValueStack => todo ! ( ) ,
107+ ValidationError :: InvalidValidationStackValType ( _) => todo ! ( ) ,
108+ ValidationError :: ExpectedAnOperand => todo ! ( ) ,
109+ ValidationError :: MemoryTooLarge => Ok ( "memory size must be at most 65536 pages (4GiB)" ) ,
110+ ValidationError :: MutationOfConstGlobal => Ok ( "global is immutable" ) ,
111+ ValidationError :: ErroneousAlignment { .. } => {
112+ Ok ( "alignment must not be larger than natural" )
113+ }
114+ ValidationError :: ValidationCtrlStackEmpty => todo ! ( ) ,
115+ ValidationError :: ElseWithoutMatchingIf => todo ! ( ) ,
116+ ValidationError :: IfWithoutMatchingElse => todo ! ( ) ,
117+ ValidationError :: MismatchedRefTypesDuringTableInit { .. } => todo ! ( ) ,
118+ ValidationError :: MismatchedRefTypesDuringTableCopy { .. } => todo ! ( ) ,
119+ ValidationError :: MismatchedRefTypesOnValidationStack { .. } => todo ! ( ) ,
120+ ValidationError :: IndirectCallToNonFuncRefTable ( _) => todo ! ( ) ,
121+ ValidationError :: ExpectedReferenceTypeOnStack ( _) => todo ! ( ) ,
122+ ValidationError :: ReferencingAnUnreferencedFunction ( _) => todo ! ( ) ,
123+ ValidationError :: InvalidSelectTypeVectorLength ( _) => todo ! ( ) ,
124+ ValidationError :: TooManyLocals ( _) => Ok ( "too many locals" ) ,
125+ ValidationError :: DuplicateExportName => Ok ( "duplicate export name" ) ,
126+ ValidationError :: UnsupportedMultipleMemoriesProposal => {
127+ Ok ( "multiple memories are not allowed (yet)" )
128+ }
129+ ValidationError :: CodeExprHasTrailingInstructions => todo ! ( ) ,
130+ ValidationError :: FunctionAndCodeSectionsHaveDifferentLengths => {
131+ Ok ( "function and code section have inconsistent lengths" )
132+ }
133+ ValidationError :: DataCountAndDataSectionsLengthAreDifferent => {
134+ Ok ( "data count and data section have inconsistent lengths" )
135+ }
136+ ValidationError :: InvalidStartFunctionSignature => todo ! ( ) ,
137+ ValidationError :: ActiveElementSegmentTypeMismatch => todo ! ( ) ,
138+ ValidationError :: I33IsNegative => todo ! ( ) ,
139+ // TODO double check if our ValidationError::MissingDataCountSection
140+ // is really the same as "data count section required" in the
141+ // reference interpreter. Because we require the data section if
142+ // there are instructions that use it. I'm unsure about the
143+ // condition that is specfied in the reference interpreter.
144+ ValidationError :: MissingDataCountSection => Ok ( "data count section required" ) ,
145+ ValidationError :: InvalidDataSegmentMode ( _) => Ok ( "malformed data segement kind" ) ,
146+ ValidationError :: InvalidElementMode ( _) => Ok ( "malformed elements segment kind" ) ,
147+
148+ // These exist only in our interpreter, because they are rare edge
149+ // cases.
150+ ValidationError :: TooManyFunctions
151+ | ValidationError :: TooManyTables
152+ | ValidationError :: TooManyMemories
153+ | ValidationError :: TooManyGlobals => Err ( WastError :: UnrepresentedValidationError (
154+ validation_error. clone ( ) ,
155+ ) ) ,
156+ }
157+ . map ( str:: to_owned)
158+ } )
159+ . map_err ( WastError :: Panic )
160+ . flatten ( )
57161}
58162
59163/// Clear the bytes and runtime instance before calling this function
@@ -280,22 +384,36 @@ fn run_directive<'a>(
280384 wast:: WastDirective :: AssertMalformed {
281385 span,
282386 module : mut modulee,
283- message : _ ,
387+ message,
284388 }
285389 | wast:: WastDirective :: AssertInvalid {
286390 span,
287391 module : mut modulee,
288- message : _ ,
392+ message,
289393 } => {
290394 let line_number = get_linenum ( contents, span) ;
291395 let cmd = get_command ( contents, span) ;
292- let result = encode ( & mut modulee) . and_then ( |bytes| {
293- let bytes = arena. alloc_slice_clone ( & bytes) ;
294- validate_instantiate ( store, bytes, linker, last_instantiated_module)
295- } ) ;
396+
397+ // Note: We can only run this assertion, if we can re-encode this
398+ // module into its binary format. This is because we cannot parse
399+ // the text format.
400+ // TODO We could compare the error message returned by the wast
401+ // crate and `message`
402+ let Ok ( bytes) = encode ( & mut modulee) else {
403+ return Ok ( Some ( AssertOutcome {
404+ line_number,
405+ command : cmd. to_owned ( ) ,
406+ maybe_error : None ,
407+ } ) ) ;
408+ } ;
409+
410+ let bytes = arena. alloc_slice_clone ( & bytes) ;
411+ let result = validate_instantiate ( store, bytes, linker, last_instantiated_module) ;
296412
297413 let maybe_assert_error = match result {
298- Ok ( _module) => Some ( WastError :: AssertInvalidButValid ) ,
414+ Ok ( _) | Err ( WastError :: FailedToLink | WastError :: WasmRuntimeError ( _) ) => {
415+ Some ( WastError :: AssertInvalidButValid )
416+ }
299417 Err ( panic_err @ WastError :: Panic ( _) ) => {
300418 return Err ( ScriptError :: new (
301419 filepath,
@@ -305,7 +423,24 @@ fn run_directive<'a>(
305423 cmd,
306424 ) )
307425 }
308- Err ( _other) => None ,
426+ Err ( WastError :: WasmError ( validation_error) ) => {
427+ match validation_error_to_wasm_testsuite_string ( & validation_error) {
428+ Ok ( actual_message) => {
429+ if actual_message == message {
430+ None
431+ } else {
432+ Some ( WastError :: UnexpectedValidationError {
433+ expected : message. to_owned ( ) ,
434+ actual : validation_error,
435+ } )
436+ }
437+ }
438+ Err ( err) => Some ( err) ,
439+ }
440+ }
441+ Err ( other_err) => {
442+ unreachable ! ( "no other errors should be possible here, got: {other_err}" )
443+ }
309444 } ;
310445
311446 Ok ( Some ( AssertOutcome {
0 commit comments