1pub mod error;
18pub mod state;
19
20use alloc::{collections::BTreeSet, vec, vec::Vec};
21
22use crate::binary::instr::{DecodedInstr, Instr, decode_instr_sequence_with_offsets};
23use crate::binary::module::Module;
24use crate::error::ByteOffset;
25use crate::types::{
26 BlockType, DataIdx, DataMode, ElemIdx, ElementInit, ElementMode, ExportDesc, FuncIdx, FuncType,
27 GlobalIdx, ImportDesc, LocalDecl, MemIdx, Mutability, RefType, TableIdx, TypeIdx, ValType,
28};
29use crate::validate::error::{ValidationError, ValidationErrorKind};
30use crate::validate::state::{ControlKind::*, OperandType, Reachability, ValidationState};
31
32pub use error::{ValidationError as Error, ValidationErrorKind as ErrorKind};
33pub use state::{
34 ControlFrame, OperandType as ValidationOperandType, Reachability as ValidationReachability,
35 TypeStack, ValidationState as FunctionValidationState,
36};
37
38impl<'a> Module<'a> {
39 pub fn validate(&self) -> Result<(), ValidationError> {
41 validate_module(self)
42 }
43}
44
45pub fn validate_module(module: &Module<'_>) -> Result<(), ValidationError> {
47 for &type_idx in &module.functions {
48 if module.types.get(type_idx.0 as usize).is_none() {
49 return Err(ValidationError {
50 offset: ByteOffset(0),
51 function: None,
52 kind: ValidationErrorKind::UnknownTypeIdx { idx: type_idx },
53 });
54 }
55 }
56
57 validate_type_definitions(module)?;
58 validate_imports(module)?;
59 validate_tables(module)?;
60 validate_memories(module)?;
61 validate_globals(module)?;
62 validate_data_segments(module)?;
63 validate_bulk_memory(module)?;
64 validate_exports(module)?;
65 validate_elements(module)?;
66 validate_start(module)?;
67
68 for (func_idx, (type_idx, code)) in module.functions.iter().zip(module.codes()).enumerate() {
69 let ty = &module.types[type_idx.0 as usize];
70 validate_function(
71 module,
72 FuncIdx(func_idx as u32),
73 ty,
74 code.locals.as_slice(),
75 code,
76 )?;
77 }
78
79 Ok(())
80}
81
82fn validate_type_definitions(module: &Module<'_>) -> Result<(), ValidationError> {
83 let offset = module
84 .section(crate::binary::section::SectionId::Type)
85 .map(|section| section.offset)
86 .unwrap_or(0);
87
88 for (idx, ty) in module.types.iter().enumerate() {
89 validate_func_type_definition_type_indices(module, TypeIdx(idx as u32), ty, offset)?;
90 }
91
92 Ok(())
93}
94
95fn validate_imports(module: &Module<'_>) -> Result<(), ValidationError> {
96 let offset = module
97 .section(crate::binary::section::SectionId::Import)
98 .map(|section| section.offset)
99 .unwrap_or(0);
100
101 for import in module.imports() {
102 match &import.desc {
103 ImportDesc::Func(type_idx) => {
104 if module.types.get(type_idx.0 as usize).is_none() {
105 return Err(ValidationError {
106 offset: ByteOffset(offset),
107 function: None,
108 kind: ValidationErrorKind::UnknownTypeIdx { idx: *type_idx },
109 });
110 }
111 }
112 ImportDesc::Table(table) => {
113 validate_reftype_type_indices(module, table.elem, None, offset)?;
114 }
115 ImportDesc::Global(global) => {
116 validate_valtype_type_indices(module, global.val_type, None, offset)?;
117 }
118 ImportDesc::Mem(_) => {}
119 }
120 }
121
122 Ok(())
123}
124
125fn validate_memories(module: &Module<'_>) -> Result<(), ValidationError> {
126 let offset = module
127 .section(crate::binary::section::SectionId::Memory)
128 .map(|section| section.offset)
129 .unwrap_or(0);
130
131 for import in module.imports() {
133 if let crate::types::ImportDesc::Mem(memory) = import.desc {
134 validate_memory_limits(memory.limits, offset)?;
135 }
136 }
137 for memory in &module.memories {
138 validate_memory_limits(memory.limits, offset)?;
139 }
140
141 Ok(())
142}
143
144fn validate_memory_limits(
145 limits: crate::types::Limits,
146 offset: usize,
147) -> Result<(), ValidationError> {
148 const MAX_PAGES: u32 = 65536;
149 if limits.min > MAX_PAGES || limits.max.is_some_and(|max| max > MAX_PAGES) {
150 return Err(ValidationError {
151 offset: ByteOffset(offset),
152 function: None,
153 kind: ValidationErrorKind::MemorySizeOutOfRange,
154 });
155 }
156 if limits.max.is_some_and(|max| limits.min > max) {
157 return Err(ValidationError {
158 offset: ByteOffset(offset),
159 function: None,
160 kind: ValidationErrorKind::MemoryMinExceedsMax,
161 });
162 }
163 Ok(())
164}
165
166fn validate_tables(module: &Module<'_>) -> Result<(), ValidationError> {
167 let offset = module
168 .section(crate::binary::section::SectionId::Table)
169 .map(|section| section.offset)
170 .unwrap_or(0);
171
172 for table in &module.tables {
173 validate_reftype_type_indices(module, table.elem, None, offset)?;
174 if table.limits.max.is_some_and(|max| table.limits.min > max) {
176 return Err(ValidationError {
177 offset: ByteOffset(offset),
178 function: None,
179 kind: ValidationErrorKind::MemoryMinExceedsMax,
180 });
181 }
182 if table.init.is_none()
185 && matches!(
186 table.elem,
187 crate::types::RefType::Typed {
188 nullable: false,
189 ..
190 }
191 )
192 {
193 return Err(ValidationError {
194 offset: ByteOffset(offset),
195 function: None,
196 kind: ValidationErrorKind::TableTypeMismatch,
197 });
198 }
199 if let Some(init) = &table.init {
200 validate_const_expr(
203 module,
204 init,
205 offset,
206 normalize_valtype(module, ValType::Ref(table.elem)),
207 ConstExprGlobalScope::ImportedPlusDefined {
208 defined_globals_available: 0,
209 },
210 ConstExprKind::GlobalInit,
211 )?;
212 }
213 }
214
215 Ok(())
216}
217
218fn validate_globals(module: &Module<'_>) -> Result<(), ValidationError> {
219 let offset = module
220 .section(crate::binary::section::SectionId::Global)
221 .map(|section| section.offset)
222 .unwrap_or(0);
223
224 for (defined_globals_available, global) in module.globals().iter().enumerate() {
225 validate_valtype_type_indices(module, global.global_type.val_type, None, offset)?;
226 validate_global_init_expr(module, global, defined_globals_available)?;
227 }
228 Ok(())
229}
230
231#[derive(Debug, Clone, Copy)]
232enum ConstExprGlobalScope {
233 ImportedPlusDefined { defined_globals_available: usize },
234 All,
235}
236
237#[derive(Debug, Clone, Copy)]
238enum ConstExprKind {
239 GlobalInit,
240 ElementExpr,
241 I32Offset,
242}
243
244fn validate_global_init_expr(
245 module: &Module<'_>,
246 global: &crate::types::Global<'_>,
247 defined_globals_available: usize,
248) -> Result<(), ValidationError> {
249 let expected = normalize_valtype(module, global.global_type.val_type);
250 validate_const_expr(
251 module,
252 global.init_expr,
253 global.init_offset,
254 expected,
255 ConstExprGlobalScope::ImportedPlusDefined {
256 defined_globals_available,
257 },
258 ConstExprKind::GlobalInit,
259 )
260}
261
262fn resolve_const_global_val_type(
263 module: &Module<'_>,
264 idx: GlobalIdx,
265 offset: usize,
266 scope: ConstExprGlobalScope,
267) -> Result<ValType, ValidationError> {
268 let imported_globals = module
269 .imports
270 .iter()
271 .filter_map(|import| match import.desc {
272 ImportDesc::Global(global) => Some(global),
273 _ => None,
274 });
275 let defined_globals = module.globals.iter().map(|global| global.global_type);
276
277 let available_globals: Vec<_> = match scope {
278 ConstExprGlobalScope::ImportedPlusDefined {
279 defined_globals_available,
280 } => imported_globals
281 .chain(defined_globals.take(defined_globals_available))
282 .collect(),
283 ConstExprGlobalScope::All => imported_globals.chain(defined_globals).collect(),
284 };
285
286 let available = available_globals.len() as u32;
287 let global_type = available_globals
288 .get(idx.0 as usize)
289 .copied()
290 .ok_or(ValidationError {
291 offset: ByteOffset(offset),
292 function: None,
293 kind: ValidationErrorKind::UnknownGlobalIdx { idx, available },
294 })?;
295
296 if global_type.mutability != Mutability::Const {
297 return Err(ValidationError {
298 offset: ByteOffset(offset),
299 function: None,
300 kind: ValidationErrorKind::MutableGlobalInInitExpr { idx },
301 });
302 }
303
304 Ok(normalize_valtype(module, global_type.val_type))
305}
306
307fn validate_data_segments(module: &Module<'_>) -> Result<(), ValidationError> {
308 if let Some(count) = module.data_count()
309 && count as usize != module.data().len()
310 {
311 return Err(ValidationError {
312 offset: ByteOffset(0),
313 function: None,
314 kind: ValidationErrorKind::UnknownDataIdx {
315 idx: DataIdx(count),
316 available: module.data().len() as u32,
317 },
318 });
319 }
320
321 for segment in module.data() {
322 if let DataMode::Active {
323 memory,
324 offset_expr,
325 offset_offset,
326 } = &segment.mode
327 {
328 resolve_memory_type(module, *memory, FuncIdx(0), *offset_offset)?;
329 validate_const_i32_expr(module, offset_expr, *offset_offset)?;
330 }
331 }
332
333 Ok(())
334}
335
336fn validate_const_i32_expr(
337 module: &Module<'_>,
338 expr: &[u8],
339 offset: usize,
340) -> Result<(), ValidationError> {
341 validate_const_expr(
342 module,
343 expr,
344 offset,
345 ValType::Num(crate::types::NumType::I32),
346 ConstExprGlobalScope::All,
347 ConstExprKind::I32Offset,
348 )
349}
350
351fn validate_const_ref_expr(
352 module: &Module<'_>,
353 expr: &[u8],
354 offset: usize,
355 expected: RefType,
356) -> Result<(), ValidationError> {
357 validate_const_expr(
358 module,
359 expr,
360 offset,
361 normalize_valtype(module, ValType::Ref(expected)),
362 ConstExprGlobalScope::All,
363 ConstExprKind::ElementExpr,
364 )
365}
366
367fn validate_const_expr(
368 module: &Module<'_>,
369 expr: &[u8],
370 offset: usize,
371 expected: ValType,
372 global_scope: ConstExprGlobalScope,
373 kind: ConstExprKind,
374) -> Result<(), ValidationError> {
375 let instrs = decode_instr_sequence_with_offsets(expr, offset).map_err(|e| ValidationError {
376 offset: e.offset,
377 function: None,
378 kind: e.into(),
379 })?;
380
381 if !matches!(
382 instrs.last().map(|decoded| &decoded.instr),
383 Some(Instr::End)
384 ) {
385 return Err(const_expr_invalid_shape_error(kind, ByteOffset(offset)));
386 }
387
388 let mut stack = Vec::new();
389 for decoded in &instrs[..instrs.len().saturating_sub(1)] {
390 validate_const_instr(module, &mut stack, decoded, global_scope, kind)?;
391 }
392
393 if stack.len() != 1 {
394 return Err(const_expr_invalid_shape_error(
395 kind,
396 instrs
397 .first()
398 .map(|decoded| decoded.offset)
399 .unwrap_or(ByteOffset(offset)),
400 ));
401 }
402
403 let found = stack.pop().expect("const expr stack length checked");
404 if !valtype_matches(found, expected) {
405 return Err(match kind {
406 ConstExprKind::GlobalInit | ConstExprKind::I32Offset => ValidationError {
407 offset: instrs
408 .first()
409 .map(|decoded| decoded.offset)
410 .unwrap_or(ByteOffset(offset)),
411 function: None,
412 kind: ValidationErrorKind::GlobalInitTypeMismatch { expected, found },
413 },
414 ConstExprKind::ElementExpr => ValidationError {
415 offset: instrs
416 .first()
417 .map(|decoded| decoded.offset)
418 .unwrap_or(ByteOffset(offset)),
419 function: None,
420 kind: ValidationErrorKind::ElementExprTypeMismatch { expected, found },
421 },
422 });
423 }
424
425 Ok(())
426}
427
428fn validate_const_instr(
429 module: &Module<'_>,
430 stack: &mut Vec<ValType>,
431 decoded: &DecodedInstr,
432 global_scope: ConstExprGlobalScope,
433 kind: ConstExprKind,
434) -> Result<(), ValidationError> {
435 match decoded.instr {
436 Instr::I32Const(_) if !matches!(kind, ConstExprKind::ElementExpr) => {
437 stack.push(ValType::Num(crate::types::NumType::I32));
438 }
439 Instr::I64Const(_) if !matches!(kind, ConstExprKind::ElementExpr) => {
440 stack.push(ValType::Num(crate::types::NumType::I64));
441 }
442 Instr::F32Const(_) if !matches!(kind, ConstExprKind::ElementExpr) => {
443 stack.push(ValType::Num(crate::types::NumType::F32));
444 }
445 Instr::F64Const(_) if !matches!(kind, ConstExprKind::ElementExpr) => {
446 stack.push(ValType::Num(crate::types::NumType::F64));
447 }
448 Instr::RefNull(ref_type) => {
449 validate_reftype_type_indices(module, ref_type, None, decoded.offset.0)?;
450 stack.push(normalize_valtype(module, ValType::Ref(ref_type)));
451 }
452 Instr::RefFunc(idx) => {
453 let type_idx = resolve_func_type_idx_for_module(module, idx, decoded.offset.0)?;
454 if !is_declared_function_ref(module, idx) {
455 return Err(ValidationError {
456 offset: decoded.offset,
457 function: None,
458 kind: ValidationErrorKind::UndeclaredFuncRef { idx },
459 });
460 }
461 stack.push(ValType::Ref(RefType::concrete(false, type_idx)));
462 }
463 Instr::GlobalGet(idx) => stack.push(resolve_const_global_val_type(
464 module,
465 idx,
466 decoded.offset.0,
467 global_scope,
468 )?),
469 Instr::I32Add | Instr::I32Sub | Instr::I32Mul
470 if matches!(kind, ConstExprKind::GlobalInit | ConstExprKind::I32Offset) =>
471 {
472 pop_const_expect(
473 stack,
474 ValType::Num(crate::types::NumType::I32),
475 decoded.offset,
476 kind,
477 )?;
478 pop_const_expect(
479 stack,
480 ValType::Num(crate::types::NumType::I32),
481 decoded.offset,
482 kind,
483 )?;
484 stack.push(ValType::Num(crate::types::NumType::I32));
485 }
486 Instr::I64Add | Instr::I64Sub | Instr::I64Mul
487 if matches!(kind, ConstExprKind::GlobalInit) =>
488 {
489 pop_const_expect(
490 stack,
491 ValType::Num(crate::types::NumType::I64),
492 decoded.offset,
493 kind,
494 )?;
495 pop_const_expect(
496 stack,
497 ValType::Num(crate::types::NumType::I64),
498 decoded.offset,
499 kind,
500 )?;
501 stack.push(ValType::Num(crate::types::NumType::I64));
502 }
503 _ => return Err(const_expr_non_constant_error(kind, decoded.offset)),
504 }
505
506 Ok(())
507}
508
509fn pop_const_expect(
510 stack: &mut Vec<ValType>,
511 expected: ValType,
512 offset: ByteOffset,
513 kind: ConstExprKind,
514) -> Result<(), ValidationError> {
515 let Some(found) = stack.pop() else {
516 return Err(match kind {
517 ConstExprKind::ElementExpr => ValidationError {
518 offset,
519 function: None,
520 kind: ValidationErrorKind::ElementExprTypeMismatch {
521 expected,
522 found: expected,
523 },
524 },
525 ConstExprKind::GlobalInit | ConstExprKind::I32Offset => ValidationError {
526 offset,
527 function: None,
528 kind: ValidationErrorKind::GlobalInitTypeMismatch {
529 expected,
530 found: expected,
531 },
532 },
533 });
534 };
535
536 if !valtype_matches(found, expected) {
537 return Err(match kind {
538 ConstExprKind::ElementExpr => ValidationError {
539 offset,
540 function: None,
541 kind: ValidationErrorKind::ElementExprTypeMismatch { expected, found },
542 },
543 ConstExprKind::GlobalInit | ConstExprKind::I32Offset => ValidationError {
544 offset,
545 function: None,
546 kind: ValidationErrorKind::GlobalInitTypeMismatch { expected, found },
547 },
548 });
549 }
550
551 Ok(())
552}
553
554fn const_expr_non_constant_error(kind: ConstExprKind, offset: ByteOffset) -> ValidationError {
555 let kind = match kind {
556 ConstExprKind::GlobalInit | ConstExprKind::I32Offset => {
557 ValidationErrorKind::NonConstantGlobalInitExpr
558 }
559 ConstExprKind::ElementExpr => ValidationErrorKind::NonConstantElementExpr,
560 };
561 ValidationError {
562 offset,
563 function: None,
564 kind,
565 }
566}
567
568fn const_expr_invalid_shape_error(kind: ConstExprKind, offset: ByteOffset) -> ValidationError {
569 let kind = match kind {
570 ConstExprKind::GlobalInit | ConstExprKind::I32Offset => {
571 ValidationErrorKind::InvalidGlobalInitExpr
572 }
573 ConstExprKind::ElementExpr => ValidationErrorKind::InvalidElementExpr,
574 };
575 ValidationError {
576 offset,
577 function: None,
578 kind,
579 }
580}
581
582fn validate_bulk_memory(module: &Module<'_>) -> Result<(), ValidationError> {
583 if module.data_count().is_some() {
584 return Ok(());
585 }
586
587 for (func_idx, code) in module.codes().iter().enumerate() {
588 let function = FuncIdx(func_idx as u32);
589 let instrs = code
590 .instructions_with_offsets()
591 .map_err(|e| ValidationError {
592 offset: e.offset,
593 function: Some(function),
594 kind: e.into(),
595 })?;
596
597 for decoded in instrs {
598 let op = match decoded.instr {
599 Instr::MemoryInit(_, _) => Some("memory.init"),
600 Instr::DataDrop(_) => Some("data.drop"),
601 _ => None,
602 };
603
604 if let Some(op) = op {
605 return Err(ValidationError {
606 offset: decoded.offset,
607 function: Some(function),
608 kind: ValidationErrorKind::MissingDataCountSection { op },
609 });
610 }
611 }
612 }
613
614 Ok(())
615}
616
617fn validate_exports(module: &Module<'_>) -> Result<(), ValidationError> {
618 let offset = module
619 .section(crate::binary::section::SectionId::Export)
620 .map(|section| section.offset)
621 .unwrap_or(0);
622 let mut names = BTreeSet::new();
623
624 for export in module.exports() {
625 if !names.insert(export.name.as_str()) {
626 return Err(ValidationError {
627 offset: ByteOffset(offset),
628 function: None,
629 kind: ValidationErrorKind::DuplicateExportName {
630 name: export.name.clone(),
631 },
632 });
633 }
634
635 match export.desc {
636 ExportDesc::Func(idx) => {
637 let _ = resolve_func_type_for_module(module, idx, offset)?;
638 }
639 ExportDesc::Table(idx) => {
640 let _ = resolve_table_type_for_module(module, idx, offset)?;
641 }
642 ExportDesc::Mem(idx) => {
643 let _ = resolve_memory_type_for_module(module, idx, offset)?;
644 }
645 ExportDesc::Global(idx) => {
646 let _ = resolve_global_type_for_module(module, idx, offset)?;
647 }
648 }
649 }
650
651 Ok(())
652}
653
654fn validate_elements(module: &Module<'_>) -> Result<(), ValidationError> {
655 let section_offset = module
656 .section(crate::binary::section::SectionId::Element)
657 .map(|section| section.offset)
658 .unwrap_or(0);
659
660 for element in module.elements() {
661 validate_reftype_type_indices(module, element.elem_type, None, section_offset)?;
662
663 if let ElementMode::Active {
664 table,
665 offset_expr,
666 offset_offset,
667 } = &element.mode
668 {
669 let table_type = resolve_table_type_for_module(module, *table, *offset_offset)?;
670 let elem_type = normalize_reftype(module, element.elem_type);
671 let matches = match &element.init {
676 crate::types::ElementInit::FuncIndices(_) => matches!(
677 table_type.elem,
678 RefType::FuncRef
679 | RefType::Typed {
680 heap: crate::types::HeapType::Func,
681 ..
682 }
683 ),
684 crate::types::ElementInit::Expressions(_) => {
685 reftype_matches(elem_type, table_type.elem)
686 }
687 };
688 if !matches {
689 return Err(ValidationError {
690 offset: ByteOffset(*offset_offset),
691 function: None,
692 kind: ValidationErrorKind::ElementTableTypeMismatch {
693 expected: table_type.elem,
694 found: elem_type,
695 },
696 });
697 }
698 validate_const_i32_expr(module, offset_expr, *offset_offset)?;
699 }
700
701 match &element.init {
702 ElementInit::FuncIndices(funcs) => {
703 for &func in funcs {
704 let _ = resolve_func_type_for_module(module, func, section_offset)?;
705 }
706 }
707 ElementInit::Expressions(exprs) => {
708 for expr in exprs {
709 validate_const_ref_expr(
710 module,
711 expr.expr,
712 expr.offset,
713 normalize_reftype(module, element.elem_type),
714 )?;
715 }
716 }
717 }
718 }
719
720 Ok(())
721}
722
723fn validate_start(module: &Module<'_>) -> Result<(), ValidationError> {
724 let Some(start) = module.start() else {
725 return Ok(());
726 };
727
728 let offset = module
729 .section(crate::binary::section::SectionId::Start)
730 .map(|section| section.offset)
731 .unwrap_or(0);
732 let ty = resolve_func_type_for_module(module, start, offset)?;
733
734 if !ty.params.is_empty() || !ty.results.is_empty() {
735 return Err(ValidationError {
736 offset: ByteOffset(offset),
737 function: None,
738 kind: ValidationErrorKind::InvalidStartFunctionType {
739 params: ty.params.clone(),
740 results: ty.results.clone(),
741 },
742 });
743 }
744
745 Ok(())
746}
747
748fn validate_function(
749 module: &Module<'_>,
750 function: FuncIdx,
751 ty: &FuncType,
752 local_decls: &[LocalDecl],
753 code: &crate::types::CodeBody<'_>,
754) -> Result<(), ValidationError> {
755 let ty = normalize_func_type(module, ty);
756 let mut locals = ty.params.clone();
757 expand_locals(module, function, &mut locals, local_decls, code.body_offset)?;
758
759 let instrs = code
760 .instructions_with_offsets()
761 .map_err(|e| ValidationError {
762 offset: e.offset,
763 function: Some(function),
764 kind: e.into(),
765 })?;
766
767 let local_inits = initial_local_inits(&locals, ty.params.len());
768 let mut state = ValidationState::new(locals, local_inits, ty.results.clone());
769
770 for decoded in &instrs {
771 validate_instr(module, function, decoded, &mut state)?;
772 }
773
774 if state.controls.len() != 1 {
775 return Err(ValidationError {
776 offset: ByteOffset(code.body_offset),
777 function: Some(function),
778 kind: ValidationErrorKind::UnterminatedControlFrames,
779 });
780 }
781
782 if ensure_frame_end_types(
783 &state,
784 state.controls[0].outer_height,
785 &state.controls[0].end_types,
786 )
787 .is_err()
788 {
789 let full_stack = concrete_stack(&state);
790 let found_len = core::cmp::min(full_stack.len(), ty.results.len());
791 let found = full_stack[full_stack.len().saturating_sub(found_len)..].to_vec();
792 return Err(ValidationError {
793 offset: final_result_offset(code, &instrs),
794 function: Some(function),
795 kind: ValidationErrorKind::FunctionResultTypeMismatch {
796 expected: ty.results.clone(),
797 found,
798 full_stack,
799 },
800 });
801 }
802
803 Ok(())
804}
805
806fn final_result_offset(code: &crate::types::CodeBody<'_>, instrs: &[DecodedInstr]) -> ByteOffset {
807 instrs
808 .last()
809 .map(|decoded| decoded.offset)
810 .unwrap_or(ByteOffset(code.body_offset))
811}
812
813fn initial_local_inits(locals: &[ValType], param_count: usize) -> Vec<bool> {
814 locals
815 .iter()
816 .enumerate()
817 .map(|(idx, ty)| idx < param_count || valtype_is_defaultable(*ty))
818 .collect()
819}
820
821fn valtype_is_defaultable(ty: ValType) -> bool {
822 match ty {
823 ValType::Num(_) | ValType::Vec(_) => true,
824 ValType::Ref(ref_type) => ref_type.is_nullable(),
825 }
826}
827
828fn validate_instr(
829 module: &Module<'_>,
830 function: FuncIdx,
831 decoded: &DecodedInstr,
832 state: &mut ValidationState,
833) -> Result<(), ValidationError> {
834 let offset = decoded.offset.0;
835
836 match &decoded.instr {
837 Instr::Unreachable => state.enter_unreachable(),
838 Instr::Nop => {}
839 Instr::Else => {
840 let (outer_height, start_types, end_types, local_inits) = {
841 let frame = state.current_frame_mut();
842 if frame.kind != If {
843 return Err(ValidationError {
844 offset: ByteOffset(offset),
845 function: Some(function),
846 kind: ValidationErrorKind::ElseOutsideIf,
847 });
848 }
849 if frame.has_else {
850 return Err(ValidationError {
851 offset: ByteOffset(offset),
852 function: Some(function),
853 kind: ValidationErrorKind::UnexpectedElse,
854 });
855 }
856 frame.has_else = true;
857 (
858 frame.outer_height,
859 frame.start_types.clone(),
860 frame.end_types.clone(),
861 frame.local_inits.clone(),
862 )
863 };
864 if let Err(found) = ensure_frame_end_types(state, outer_height, &end_types) {
867 return Err(ValidationError {
868 offset: ByteOffset(offset),
869 function: Some(function),
870 kind: ValidationErrorKind::ControlResultTypeMismatch {
871 expected: end_types.clone(),
872 found,
873 },
874 });
875 }
876 pop_control_result_types(function, state, &end_types, offset)?;
877 state.operands.truncate(outer_height);
878 state.local_inits = local_inits;
879 for ty in start_types {
880 state.operands.push(ty);
881 }
882 let floor = state.operands.len();
883 let frame = state.current_frame_mut();
884 frame.stack_floor = floor;
885 state.reachability = Reachability::Reachable;
886 }
887 Instr::Block(block_type) => {
888 let sig = resolve_block_type(module, function, *block_type, offset)?;
889 pop_exact(function, state, &sig.params, offset)?;
890 state.push_frame(Block, *block_type, sig.params, sig.results);
891 }
892 Instr::Loop(block_type) => {
893 let sig = resolve_block_type(module, function, *block_type, offset)?;
894 pop_exact(function, state, &sig.params, offset)?;
895 state.push_frame(Loop, *block_type, sig.params, sig.results);
896 }
897 Instr::If(block_type) => {
898 pop_expect(
899 function,
900 state,
901 ValType::Num(crate::types::NumType::I32),
902 offset,
903 "if",
904 )?;
905 let sig = resolve_block_type(module, function, *block_type, offset)?;
906 pop_exact(function, state, &sig.params, offset)?;
907 state.push_frame(If, *block_type, sig.params, sig.results);
908 }
909 Instr::End => {
910 if state.controls.len() > 1 {
911 finish_frame(function, state, offset)?;
912 }
913 }
914 Instr::Br(label) => {
915 let label_types = validate_label(function, state, *label, offset)?.to_vec();
916 pop_branch_types(function, state, *label, &label_types, offset)?;
917 state.enter_unreachable();
918 }
919 Instr::BrIf(label) => {
920 pop_expect(
921 function,
922 state,
923 ValType::Num(crate::types::NumType::I32),
924 offset,
925 "br_if",
926 )?;
927 let label_types = validate_label(function, state, *label, offset)?.to_vec();
928 pop_branch_types(function, state, *label, &label_types, offset)?;
929 for ty in label_types {
930 state.operands.push(ty);
931 }
932 }
933 Instr::BrOnNull(label) => {
934 let label_types = validate_label(function, state, *label, offset)?.to_vec();
935 let found = pop_ref_type(function, state, offset, "br_on_null")?;
936 pop_branch_types(function, state, *label, &label_types, offset)?;
937 for ty in label_types {
938 state.operands.push(ty);
939 }
940 match found {
941 Some(found) => state.operands.push(ValType::Ref(found.as_non_null())),
942 None => state.operands.push_bottom(),
943 }
944 }
945 Instr::BrOnNonNull(label) => {
946 let label_types = validate_label(function, state, *label, offset)?.to_vec();
947 let Some((ValType::Ref(expected), rest)) = label_types.split_last() else {
948 return Err(ValidationError {
949 offset: ByteOffset(offset),
950 function: Some(function),
951 kind: ValidationErrorKind::InvalidBrOnNonNullTarget {
952 label: *label,
953 found: label_types,
954 },
955 });
956 };
957 let found = pop_ref_type(function, state, offset, "br_on_non_null")?;
958 let expected_input = expected.as_nullable();
959 if let Some(found) = found
960 && !reftype_matches(found, expected_input)
961 {
962 return Err(ValidationError {
963 offset: ByteOffset(offset),
964 function: Some(function),
965 kind: ValidationErrorKind::TypeMismatch {
966 op: "br_on_non_null",
967 expected: ValType::Ref(expected_input),
968 found: ValType::Ref(found),
969 },
970 });
971 }
972 pop_branch_types(function, state, *label, rest, offset)?;
973 for ty in rest {
974 state.operands.push(*ty);
975 }
976 }
977 Instr::BrTable { targets, default } => {
978 pop_expect(
979 function,
980 state,
981 ValType::Num(crate::types::NumType::I32),
982 offset,
983 "br_table",
984 )?;
985 let default_types = validate_label(function, state, *default, offset)?.to_vec();
986 for label in targets {
990 let label_types = validate_label(function, state, *label, offset)?;
991 if label_types.len() != default_types.len() {
992 return Err(ValidationError {
993 offset: ByteOffset(offset),
994 function: Some(function),
995 kind: ValidationErrorKind::InconsistentBranchTypes {
996 expected: default_types.clone(),
997 found: label_types.to_vec(),
998 },
999 });
1000 }
1001 ensure_stack_types(state, label_types).map_err(|found| ValidationError {
1002 offset: ByteOffset(offset),
1003 function: Some(function),
1004 kind: ValidationErrorKind::BranchTypeMismatch {
1005 label: *label,
1006 expected: label_types.to_vec(),
1007 found,
1008 },
1009 })?;
1010 }
1011 ensure_stack_types(state, &default_types).map_err(|found| ValidationError {
1012 offset: ByteOffset(offset),
1013 function: Some(function),
1014 kind: ValidationErrorKind::BranchTypeMismatch {
1015 label: *default,
1016 expected: default_types.clone(),
1017 found,
1018 },
1019 })?;
1020 pop_exact(function, state, &default_types, offset)?;
1021 state.enter_unreachable();
1022 }
1023 Instr::Return => {
1024 let expected = state.controls[0].end_types.clone();
1025 pop_control_result_types(function, state, &expected, offset)?;
1026 state.enter_unreachable();
1027 }
1028 Instr::Call(idx) => {
1029 let ty = resolve_func_type(module, *idx, function, offset)?;
1030 pop_exact(function, state, &ty.params, offset)?;
1031 for result in &ty.results {
1032 state.operands.push(*result);
1033 }
1034 }
1035 Instr::ReturnCall(idx) => {
1036 let ty = resolve_func_type(module, *idx, function, offset)?;
1037 validate_tail_call_results(function, state, &ty.results, offset)?;
1038 pop_exact(function, state, &ty.params, offset)?;
1039 state.enter_unreachable();
1040 }
1041 Instr::CallRef(type_idx) => {
1042 let ty = resolve_type(module, *type_idx, Some(function), offset)?;
1043 pop_expect(
1044 function,
1045 state,
1046 ValType::Ref(RefType::concrete(
1047 true,
1048 canonicalize_func_type_idx(module, *type_idx),
1049 )),
1050 offset,
1051 "call_ref",
1052 )?;
1053 pop_exact(function, state, &ty.params, offset)?;
1054 for result in &ty.results {
1055 state.operands.push(*result);
1056 }
1057 }
1058 Instr::ReturnCallRef(type_idx) => {
1059 let ty = resolve_type(module, *type_idx, Some(function), offset)?;
1060 validate_tail_call_results(function, state, &ty.results, offset)?;
1061 pop_expect(
1062 function,
1063 state,
1064 ValType::Ref(RefType::concrete(
1065 true,
1066 canonicalize_func_type_idx(module, *type_idx),
1067 )),
1068 offset,
1069 "return_call_ref",
1070 )?;
1071 pop_exact(function, state, &ty.params, offset)?;
1072 state.enter_unreachable();
1073 }
1074 Instr::CallIndirect {
1075 type_idx,
1076 table_idx,
1077 } => {
1078 let table_type =
1079 resolve_table_type_with_context(module, *table_idx, Some(function), offset)?;
1080 if !reftype_matches(table_type.elem, RefType::FuncRef) {
1081 return Err(ValidationError {
1082 offset: ByteOffset(offset),
1083 function: Some(function),
1084 kind: ValidationErrorKind::InvalidCallIndirectTableType {
1085 expected: RefType::FuncRef,
1086 found: table_type.elem,
1087 },
1088 });
1089 }
1090 let ty = resolve_type(module, *type_idx, Some(function), offset)?;
1091 pop_expect(
1092 function,
1093 state,
1094 ValType::Num(crate::types::NumType::I32),
1095 offset,
1096 "call_indirect",
1097 )?;
1098 pop_exact(function, state, &ty.params, offset)?;
1099 for result in &ty.results {
1100 state.operands.push(*result);
1101 }
1102 }
1103 Instr::ReturnCallIndirect {
1104 type_idx,
1105 table_idx,
1106 } => {
1107 let table_type =
1108 resolve_table_type_with_context(module, *table_idx, Some(function), offset)?;
1109 if !reftype_matches(table_type.elem, RefType::FuncRef) {
1110 return Err(ValidationError {
1111 offset: ByteOffset(offset),
1112 function: Some(function),
1113 kind: ValidationErrorKind::InvalidCallIndirectTableType {
1114 expected: RefType::FuncRef,
1115 found: table_type.elem,
1116 },
1117 });
1118 }
1119 let ty = resolve_type(module, *type_idx, Some(function), offset)?;
1120 validate_tail_call_results(function, state, &ty.results, offset)?;
1121 pop_expect(
1122 function,
1123 state,
1124 ValType::Num(crate::types::NumType::I32),
1125 offset,
1126 "return_call_indirect",
1127 )?;
1128 pop_exact(function, state, &ty.params, offset)?;
1129 state.enter_unreachable();
1130 }
1131 Instr::Drop => {
1132 pop_any(function, state, offset, "drop")?;
1133 }
1134 Instr::Select => {
1135 pop_expect(
1136 function,
1137 state,
1138 ValType::Num(crate::types::NumType::I32),
1139 offset,
1140 "select",
1141 )?;
1142 let rhs = pop_operand_type(function, state, offset, "select")?;
1143 let lhs = pop_operand_type(function, state, offset, "select")?;
1144 match (lhs, rhs) {
1145 (OperandType::Bottom, OperandType::Bottom) => state.operands.push_bottom(),
1146 (OperandType::Bottom, OperandType::Typed(rhs))
1147 | (OperandType::Typed(rhs), OperandType::Bottom) => state.operands.push(rhs),
1148 (OperandType::Typed(lhs), OperandType::Typed(rhs)) => {
1149 if lhs != rhs {
1150 return Err(ValidationError {
1151 offset: ByteOffset(offset),
1152 function: Some(function),
1153 kind: ValidationErrorKind::SelectOperandTypeMismatch {
1154 expected: lhs,
1155 found: vec![lhs, rhs],
1156 },
1157 });
1158 }
1159 if !matches!(lhs, ValType::Num(_) | ValType::Vec(_)) {
1162 return Err(ValidationError {
1163 offset: ByteOffset(offset),
1164 function: Some(function),
1165 kind: ValidationErrorKind::SelectOperandTypeMismatch {
1166 expected: ValType::Num(crate::types::NumType::I32),
1167 found: vec![lhs, rhs],
1168 },
1169 });
1170 }
1171 state.operands.push(lhs);
1172 }
1173 }
1174 }
1175 Instr::SelectTyped(types) => {
1176 if types.len() != 1 {
1177 return Err(ValidationError {
1178 offset: ByteOffset(offset),
1179 function: Some(function),
1180 kind: ValidationErrorKind::InvalidSelectResultArity { found: types.len() },
1181 });
1182 }
1183 validate_valtype_type_indices(module, types[0], Some(function), offset)?;
1184 let expected = normalize_valtype(module, types[0]);
1185 pop_expect(
1186 function,
1187 state,
1188 ValType::Num(crate::types::NumType::I32),
1189 offset,
1190 "select_typed",
1191 )?;
1192 let rhs = pop_operand_type(function, state, offset, "select_typed")?;
1193 let lhs = pop_operand_type(function, state, offset, "select_typed")?;
1194 if !operand_matches(lhs, expected) || !operand_matches(rhs, expected) {
1195 return Err(ValidationError {
1196 offset: ByteOffset(offset),
1197 function: Some(function),
1198 kind: ValidationErrorKind::SelectOperandTypeMismatch {
1199 expected,
1200 found: vec![
1201 operand_to_valtype(lhs, expected),
1202 operand_to_valtype(rhs, expected),
1203 ],
1204 },
1205 });
1206 }
1207 state.operands.push(expected);
1208 }
1209 Instr::LocalGet(idx) => {
1210 let ty = *state.locals.get(idx.0 as usize).ok_or(ValidationError {
1211 offset: ByteOffset(offset),
1212 function: Some(function),
1213 kind: ValidationErrorKind::UnknownLocalIdx { idx: *idx },
1214 })?;
1215 if !state
1216 .local_inits
1217 .get(idx.0 as usize)
1218 .copied()
1219 .unwrap_or(false)
1220 {
1221 return Err(ValidationError {
1222 offset: ByteOffset(offset),
1223 function: Some(function),
1224 kind: ValidationErrorKind::UninitializedLocal { idx: *idx },
1225 });
1226 }
1227 state.operands.push(ty);
1228 }
1229 Instr::LocalSet(idx) => {
1230 let ty = *state.locals.get(idx.0 as usize).ok_or(ValidationError {
1231 offset: ByteOffset(offset),
1232 function: Some(function),
1233 kind: ValidationErrorKind::UnknownLocalIdx { idx: *idx },
1234 })?;
1235 pop_expect(function, state, ty, offset, "local.set")?;
1236 state.local_inits[idx.0 as usize] = true;
1237 }
1238 Instr::LocalTee(idx) => {
1239 let ty = *state.locals.get(idx.0 as usize).ok_or(ValidationError {
1240 offset: ByteOffset(offset),
1241 function: Some(function),
1242 kind: ValidationErrorKind::UnknownLocalIdx { idx: *idx },
1243 })?;
1244 pop_expect(function, state, ty, offset, "local.tee")?;
1245 state.local_inits[idx.0 as usize] = true;
1246 state.operands.push(ty);
1247 }
1248 Instr::GlobalGet(idx) => {
1249 let ty = resolve_global_type(module, *idx, function, offset)?;
1250 state.operands.push(ty.val_type);
1251 }
1252 Instr::GlobalSet(idx) => {
1253 let ty = resolve_global_type(module, *idx, function, offset)?;
1254 if ty.mutability != Mutability::Var {
1255 return Err(ValidationError {
1256 offset: ByteOffset(offset),
1257 function: Some(function),
1258 kind: ValidationErrorKind::ImmutableGlobalSet { idx: *idx },
1259 });
1260 }
1261 pop_expect(function, state, ty.val_type, offset, "global.set")?;
1262 }
1263 Instr::TableGet(idx) => {
1264 let ty = resolve_table_type_with_context(module, *idx, Some(function), offset)?;
1265 pop_expect(
1266 function,
1267 state,
1268 ValType::Num(crate::types::NumType::I32),
1269 offset,
1270 "table.get",
1271 )?;
1272 state.operands.push(ValType::Ref(ty.elem));
1273 }
1274 Instr::TableSet(idx) => {
1275 let ty = resolve_table_type_with_context(module, *idx, Some(function), offset)?;
1276 pop_expect(function, state, ValType::Ref(ty.elem), offset, "table.set")?;
1277 pop_expect(
1278 function,
1279 state,
1280 ValType::Num(crate::types::NumType::I32),
1281 offset,
1282 "table.set",
1283 )?;
1284 }
1285 Instr::V128Load(memarg) => validate_load(
1286 module,
1287 function,
1288 state,
1289 offset,
1290 MemLoadValidation {
1291 op: "v128.load",
1292 memory: memarg.memory,
1293 found_align: memarg.align,
1294 max_align: 4,
1295 result: ValType::Vec(crate::types::VecType::V128),
1296 },
1297 )?,
1298 Instr::V128Load8x8S(memarg) | Instr::V128Load8x8U(memarg) => validate_load(
1299 module,
1300 function,
1301 state,
1302 offset,
1303 MemLoadValidation {
1304 op: "v128.load8x8",
1305 memory: memarg.memory,
1306 found_align: memarg.align,
1307 max_align: 3,
1308 result: ValType::Vec(crate::types::VecType::V128),
1309 },
1310 )?,
1311 Instr::V128Load16x4S(memarg) | Instr::V128Load16x4U(memarg) => validate_load(
1312 module,
1313 function,
1314 state,
1315 offset,
1316 MemLoadValidation {
1317 op: "v128.load16x4",
1318 memory: memarg.memory,
1319 found_align: memarg.align,
1320 max_align: 3,
1321 result: ValType::Vec(crate::types::VecType::V128),
1322 },
1323 )?,
1324 Instr::V128Load32x2S(memarg) | Instr::V128Load32x2U(memarg) => validate_load(
1325 module,
1326 function,
1327 state,
1328 offset,
1329 MemLoadValidation {
1330 op: "v128.load32x2",
1331 memory: memarg.memory,
1332 found_align: memarg.align,
1333 max_align: 3,
1334 result: ValType::Vec(crate::types::VecType::V128),
1335 },
1336 )?,
1337 Instr::V128Load8Splat(memarg) => validate_load(
1338 module,
1339 function,
1340 state,
1341 offset,
1342 MemLoadValidation {
1343 op: "v128.load8_splat",
1344 memory: memarg.memory,
1345 found_align: memarg.align,
1346 max_align: 0,
1347 result: ValType::Vec(crate::types::VecType::V128),
1348 },
1349 )?,
1350 Instr::V128Load16Splat(memarg) => validate_load(
1351 module,
1352 function,
1353 state,
1354 offset,
1355 MemLoadValidation {
1356 op: "v128.load16_splat",
1357 memory: memarg.memory,
1358 found_align: memarg.align,
1359 max_align: 1,
1360 result: ValType::Vec(crate::types::VecType::V128),
1361 },
1362 )?,
1363 Instr::V128Load32Splat(memarg) => validate_load(
1364 module,
1365 function,
1366 state,
1367 offset,
1368 MemLoadValidation {
1369 op: "v128.load32_splat",
1370 memory: memarg.memory,
1371 found_align: memarg.align,
1372 max_align: 2,
1373 result: ValType::Vec(crate::types::VecType::V128),
1374 },
1375 )?,
1376 Instr::V128Load64Splat(memarg) => validate_load(
1377 module,
1378 function,
1379 state,
1380 offset,
1381 MemLoadValidation {
1382 op: "v128.load64_splat",
1383 memory: memarg.memory,
1384 found_align: memarg.align,
1385 max_align: 3,
1386 result: ValType::Vec(crate::types::VecType::V128),
1387 },
1388 )?,
1389 Instr::V128Load32Zero(memarg) => validate_load(
1390 module,
1391 function,
1392 state,
1393 offset,
1394 MemLoadValidation {
1395 op: "v128.load32_zero",
1396 memory: memarg.memory,
1397 found_align: memarg.align,
1398 max_align: 2,
1399 result: ValType::Vec(crate::types::VecType::V128),
1400 },
1401 )?,
1402 Instr::V128Load64Zero(memarg) => validate_load(
1403 module,
1404 function,
1405 state,
1406 offset,
1407 MemLoadValidation {
1408 op: "v128.load64_zero",
1409 memory: memarg.memory,
1410 found_align: memarg.align,
1411 max_align: 3,
1412 result: ValType::Vec(crate::types::VecType::V128),
1413 },
1414 )?,
1415 Instr::V128Store(memarg) => validate_store(
1416 module,
1417 function,
1418 state,
1419 offset,
1420 MemStoreValidation {
1421 op: "v128.store",
1422 memory: memarg.memory,
1423 found_align: memarg.align,
1424 max_align: 4,
1425 stored: ValType::Vec(crate::types::VecType::V128),
1426 },
1427 )?,
1428 Instr::V128Load8Lane { memarg, lane } => validate_simd_load_lane(
1429 module,
1430 function,
1431 state,
1432 offset,
1433 SimdLaneValidation {
1434 op: "v128.load8_lane",
1435 memory: memarg.memory,
1436 found_align: memarg.align,
1437 max_align: 0,
1438 lane: *lane,
1439 max_lane: 15,
1440 },
1441 )?,
1442 Instr::V128Load16Lane { memarg, lane } => validate_simd_load_lane(
1443 module,
1444 function,
1445 state,
1446 offset,
1447 SimdLaneValidation {
1448 op: "v128.load16_lane",
1449 memory: memarg.memory,
1450 found_align: memarg.align,
1451 max_align: 1,
1452 lane: *lane,
1453 max_lane: 7,
1454 },
1455 )?,
1456 Instr::V128Load32Lane { memarg, lane } => validate_simd_load_lane(
1457 module,
1458 function,
1459 state,
1460 offset,
1461 SimdLaneValidation {
1462 op: "v128.load32_lane",
1463 memory: memarg.memory,
1464 found_align: memarg.align,
1465 max_align: 2,
1466 lane: *lane,
1467 max_lane: 3,
1468 },
1469 )?,
1470 Instr::V128Load64Lane { memarg, lane } => validate_simd_load_lane(
1471 module,
1472 function,
1473 state,
1474 offset,
1475 SimdLaneValidation {
1476 op: "v128.load64_lane",
1477 memory: memarg.memory,
1478 found_align: memarg.align,
1479 max_align: 3,
1480 lane: *lane,
1481 max_lane: 1,
1482 },
1483 )?,
1484 Instr::V128Store8Lane { memarg, lane } => validate_simd_store_lane(
1485 module,
1486 function,
1487 state,
1488 offset,
1489 SimdLaneValidation {
1490 op: "v128.store8_lane",
1491 memory: memarg.memory,
1492 found_align: memarg.align,
1493 max_align: 0,
1494 lane: *lane,
1495 max_lane: 15,
1496 },
1497 )?,
1498 Instr::V128Store16Lane { memarg, lane } => validate_simd_store_lane(
1499 module,
1500 function,
1501 state,
1502 offset,
1503 SimdLaneValidation {
1504 op: "v128.store16_lane",
1505 memory: memarg.memory,
1506 found_align: memarg.align,
1507 max_align: 1,
1508 lane: *lane,
1509 max_lane: 7,
1510 },
1511 )?,
1512 Instr::V128Store32Lane { memarg, lane } => validate_simd_store_lane(
1513 module,
1514 function,
1515 state,
1516 offset,
1517 SimdLaneValidation {
1518 op: "v128.store32_lane",
1519 memory: memarg.memory,
1520 found_align: memarg.align,
1521 max_align: 2,
1522 lane: *lane,
1523 max_lane: 3,
1524 },
1525 )?,
1526 Instr::V128Store64Lane { memarg, lane } => validate_simd_store_lane(
1527 module,
1528 function,
1529 state,
1530 offset,
1531 SimdLaneValidation {
1532 op: "v128.store64_lane",
1533 memory: memarg.memory,
1534 found_align: memarg.align,
1535 max_align: 3,
1536 lane: *lane,
1537 max_lane: 1,
1538 },
1539 )?,
1540 Instr::I32Load(memarg) => validate_load(
1541 module,
1542 function,
1543 state,
1544 offset,
1545 MemLoadValidation {
1546 op: "i32.load",
1547 memory: memarg.memory,
1548 found_align: memarg.align,
1549 max_align: 2,
1550 result: ValType::Num(crate::types::NumType::I32),
1551 },
1552 )?,
1553 Instr::I64Load(memarg) => validate_load(
1554 module,
1555 function,
1556 state,
1557 offset,
1558 MemLoadValidation {
1559 op: "i64.load",
1560 memory: memarg.memory,
1561 found_align: memarg.align,
1562 max_align: 3,
1563 result: ValType::Num(crate::types::NumType::I64),
1564 },
1565 )?,
1566 Instr::F32Load(memarg) => validate_load(
1567 module,
1568 function,
1569 state,
1570 offset,
1571 MemLoadValidation {
1572 op: "f32.load",
1573 memory: memarg.memory,
1574 found_align: memarg.align,
1575 max_align: 2,
1576 result: ValType::Num(crate::types::NumType::F32),
1577 },
1578 )?,
1579 Instr::F64Load(memarg) => validate_load(
1580 module,
1581 function,
1582 state,
1583 offset,
1584 MemLoadValidation {
1585 op: "f64.load",
1586 memory: memarg.memory,
1587 found_align: memarg.align,
1588 max_align: 3,
1589 result: ValType::Num(crate::types::NumType::F64),
1590 },
1591 )?,
1592 Instr::I32Load8S(memarg) | Instr::I32Load8U(memarg) => validate_load(
1593 module,
1594 function,
1595 state,
1596 offset,
1597 MemLoadValidation {
1598 op: "i32.load8",
1599 memory: memarg.memory,
1600 found_align: memarg.align,
1601 max_align: 0,
1602 result: ValType::Num(crate::types::NumType::I32),
1603 },
1604 )?,
1605 Instr::I32Load16S(memarg) | Instr::I32Load16U(memarg) => validate_load(
1606 module,
1607 function,
1608 state,
1609 offset,
1610 MemLoadValidation {
1611 op: "i32.load16",
1612 memory: memarg.memory,
1613 found_align: memarg.align,
1614 max_align: 1,
1615 result: ValType::Num(crate::types::NumType::I32),
1616 },
1617 )?,
1618 Instr::I64Load8S(memarg) | Instr::I64Load8U(memarg) => validate_load(
1619 module,
1620 function,
1621 state,
1622 offset,
1623 MemLoadValidation {
1624 op: "i64.load8",
1625 memory: memarg.memory,
1626 found_align: memarg.align,
1627 max_align: 0,
1628 result: ValType::Num(crate::types::NumType::I64),
1629 },
1630 )?,
1631 Instr::I64Load16S(memarg) | Instr::I64Load16U(memarg) => validate_load(
1632 module,
1633 function,
1634 state,
1635 offset,
1636 MemLoadValidation {
1637 op: "i64.load16",
1638 memory: memarg.memory,
1639 found_align: memarg.align,
1640 max_align: 1,
1641 result: ValType::Num(crate::types::NumType::I64),
1642 },
1643 )?,
1644 Instr::I64Load32S(memarg) | Instr::I64Load32U(memarg) => validate_load(
1645 module,
1646 function,
1647 state,
1648 offset,
1649 MemLoadValidation {
1650 op: "i64.load32",
1651 memory: memarg.memory,
1652 found_align: memarg.align,
1653 max_align: 2,
1654 result: ValType::Num(crate::types::NumType::I64),
1655 },
1656 )?,
1657 Instr::I32Store(memarg) => validate_store(
1658 module,
1659 function,
1660 state,
1661 offset,
1662 MemStoreValidation {
1663 op: "i32.store",
1664 memory: memarg.memory,
1665 found_align: memarg.align,
1666 max_align: 2,
1667 stored: ValType::Num(crate::types::NumType::I32),
1668 },
1669 )?,
1670 Instr::I64Store(memarg) => validate_store(
1671 module,
1672 function,
1673 state,
1674 offset,
1675 MemStoreValidation {
1676 op: "i64.store",
1677 memory: memarg.memory,
1678 found_align: memarg.align,
1679 max_align: 3,
1680 stored: ValType::Num(crate::types::NumType::I64),
1681 },
1682 )?,
1683 Instr::F32Store(memarg) => validate_store(
1684 module,
1685 function,
1686 state,
1687 offset,
1688 MemStoreValidation {
1689 op: "f32.store",
1690 memory: memarg.memory,
1691 found_align: memarg.align,
1692 max_align: 2,
1693 stored: ValType::Num(crate::types::NumType::F32),
1694 },
1695 )?,
1696 Instr::F64Store(memarg) => validate_store(
1697 module,
1698 function,
1699 state,
1700 offset,
1701 MemStoreValidation {
1702 op: "f64.store",
1703 memory: memarg.memory,
1704 found_align: memarg.align,
1705 max_align: 3,
1706 stored: ValType::Num(crate::types::NumType::F64),
1707 },
1708 )?,
1709 Instr::I32Store8(memarg) => validate_store(
1710 module,
1711 function,
1712 state,
1713 offset,
1714 MemStoreValidation {
1715 op: "i32.store8",
1716 memory: memarg.memory,
1717 found_align: memarg.align,
1718 max_align: 0,
1719 stored: ValType::Num(crate::types::NumType::I32),
1720 },
1721 )?,
1722 Instr::I32Store16(memarg) => validate_store(
1723 module,
1724 function,
1725 state,
1726 offset,
1727 MemStoreValidation {
1728 op: "i32.store16",
1729 memory: memarg.memory,
1730 found_align: memarg.align,
1731 max_align: 1,
1732 stored: ValType::Num(crate::types::NumType::I32),
1733 },
1734 )?,
1735 Instr::I64Store8(memarg) => validate_store(
1736 module,
1737 function,
1738 state,
1739 offset,
1740 MemStoreValidation {
1741 op: "i64.store8",
1742 memory: memarg.memory,
1743 found_align: memarg.align,
1744 max_align: 0,
1745 stored: ValType::Num(crate::types::NumType::I64),
1746 },
1747 )?,
1748 Instr::I64Store16(memarg) => validate_store(
1749 module,
1750 function,
1751 state,
1752 offset,
1753 MemStoreValidation {
1754 op: "i64.store16",
1755 memory: memarg.memory,
1756 found_align: memarg.align,
1757 max_align: 1,
1758 stored: ValType::Num(crate::types::NumType::I64),
1759 },
1760 )?,
1761 Instr::I64Store32(memarg) => validate_store(
1762 module,
1763 function,
1764 state,
1765 offset,
1766 MemStoreValidation {
1767 op: "i64.store32",
1768 memory: memarg.memory,
1769 found_align: memarg.align,
1770 max_align: 2,
1771 stored: ValType::Num(crate::types::NumType::I64),
1772 },
1773 )?,
1774 Instr::MemoryInit(data_idx, mem_idx) => {
1775 resolve_data_segment(module, *data_idx, function, offset)?;
1776 resolve_memory_type(module, *mem_idx, function, offset)?;
1777 pop_expect(
1778 function,
1779 state,
1780 ValType::Num(crate::types::NumType::I32),
1781 offset,
1782 "memory.init",
1783 )?;
1784 pop_expect(
1785 function,
1786 state,
1787 ValType::Num(crate::types::NumType::I32),
1788 offset,
1789 "memory.init",
1790 )?;
1791 pop_expect(
1792 function,
1793 state,
1794 ValType::Num(crate::types::NumType::I32),
1795 offset,
1796 "memory.init",
1797 )?;
1798 }
1799 Instr::DataDrop(data_idx) => {
1800 resolve_data_segment(module, *data_idx, function, offset)?;
1801 }
1802 Instr::MemoryCopy { dst, src } => {
1803 resolve_memory_type(module, *dst, function, offset)?;
1804 resolve_memory_type(module, *src, function, offset)?;
1805 pop_expect(
1806 function,
1807 state,
1808 ValType::Num(crate::types::NumType::I32),
1809 offset,
1810 "memory.copy",
1811 )?;
1812 pop_expect(
1813 function,
1814 state,
1815 ValType::Num(crate::types::NumType::I32),
1816 offset,
1817 "memory.copy",
1818 )?;
1819 pop_expect(
1820 function,
1821 state,
1822 ValType::Num(crate::types::NumType::I32),
1823 offset,
1824 "memory.copy",
1825 )?;
1826 }
1827 Instr::MemoryFill(mem_idx) => {
1828 resolve_memory_type(module, *mem_idx, function, offset)?;
1829 pop_expect(
1830 function,
1831 state,
1832 ValType::Num(crate::types::NumType::I32),
1833 offset,
1834 "memory.fill",
1835 )?;
1836 pop_expect(
1837 function,
1838 state,
1839 ValType::Num(crate::types::NumType::I32),
1840 offset,
1841 "memory.fill",
1842 )?;
1843 pop_expect(
1844 function,
1845 state,
1846 ValType::Num(crate::types::NumType::I32),
1847 offset,
1848 "memory.fill",
1849 )?;
1850 }
1851 Instr::TableInit {
1852 elem_idx,
1853 table_idx,
1854 } => {
1855 let elem = resolve_element_segment(module, *elem_idx, function, offset)?;
1856 let elem_type = normalize_reftype(module, elem.elem_type);
1857 let table =
1858 resolve_table_type_with_context(module, *table_idx, Some(function), offset)?;
1859 if !reftype_matches(elem_type, table.elem) {
1860 return Err(ValidationError {
1861 offset: ByteOffset(offset),
1862 function: Some(function),
1863 kind: ValidationErrorKind::ElementTableTypeMismatch {
1864 expected: table.elem,
1865 found: elem_type,
1866 },
1867 });
1868 }
1869 pop_expect(
1870 function,
1871 state,
1872 ValType::Num(crate::types::NumType::I32),
1873 offset,
1874 "table.init",
1875 )?;
1876 pop_expect(
1877 function,
1878 state,
1879 ValType::Num(crate::types::NumType::I32),
1880 offset,
1881 "table.init",
1882 )?;
1883 pop_expect(
1884 function,
1885 state,
1886 ValType::Num(crate::types::NumType::I32),
1887 offset,
1888 "table.init",
1889 )?;
1890 }
1891 Instr::ElemDrop(elem_idx) => {
1892 let _ = resolve_element_segment(module, *elem_idx, function, offset)?;
1893 }
1894 Instr::TableCopy { dst, src } => {
1895 let dst_ty = resolve_table_type_with_context(module, *dst, Some(function), offset)?;
1896 let src_ty = resolve_table_type_with_context(module, *src, Some(function), offset)?;
1897 if !reftype_matches(src_ty.elem, dst_ty.elem)
1898 || !reftype_matches(dst_ty.elem, src_ty.elem)
1899 {
1900 return Err(ValidationError {
1901 offset: ByteOffset(offset),
1902 function: Some(function),
1903 kind: ValidationErrorKind::ElementTableTypeMismatch {
1904 expected: dst_ty.elem,
1905 found: src_ty.elem,
1906 },
1907 });
1908 }
1909 pop_expect(
1910 function,
1911 state,
1912 ValType::Num(crate::types::NumType::I32),
1913 offset,
1914 "table.copy",
1915 )?;
1916 pop_expect(
1917 function,
1918 state,
1919 ValType::Num(crate::types::NumType::I32),
1920 offset,
1921 "table.copy",
1922 )?;
1923 pop_expect(
1924 function,
1925 state,
1926 ValType::Num(crate::types::NumType::I32),
1927 offset,
1928 "table.copy",
1929 )?;
1930 }
1931 Instr::TableGrow(idx) => {
1932 let ty = resolve_table_type_with_context(module, *idx, Some(function), offset)?;
1933 pop_expect(
1934 function,
1935 state,
1936 ValType::Num(crate::types::NumType::I32),
1937 offset,
1938 "table.grow",
1939 )?;
1940 pop_expect(function, state, ValType::Ref(ty.elem), offset, "table.grow")?;
1941 state
1942 .operands
1943 .push(ValType::Num(crate::types::NumType::I32));
1944 }
1945 Instr::TableSize(idx) => {
1946 let _ = resolve_table_type_with_context(module, *idx, Some(function), offset)?;
1947 state
1948 .operands
1949 .push(ValType::Num(crate::types::NumType::I32));
1950 }
1951 Instr::TableFill(idx) => {
1952 let ty = resolve_table_type_with_context(module, *idx, Some(function), offset)?;
1953 pop_expect(
1954 function,
1955 state,
1956 ValType::Num(crate::types::NumType::I32),
1957 offset,
1958 "table.fill",
1959 )?;
1960 pop_expect(function, state, ValType::Ref(ty.elem), offset, "table.fill")?;
1961 pop_expect(
1962 function,
1963 state,
1964 ValType::Num(crate::types::NumType::I32),
1965 offset,
1966 "table.fill",
1967 )?;
1968 }
1969 Instr::MemorySize(idx) => {
1970 resolve_memory_type(module, *idx, function, offset)?;
1971 state
1972 .operands
1973 .push(ValType::Num(crate::types::NumType::I32));
1974 }
1975 Instr::MemoryGrow(idx) => {
1976 resolve_memory_type(module, *idx, function, offset)?;
1977 pop_expect(
1978 function,
1979 state,
1980 ValType::Num(crate::types::NumType::I32),
1981 offset,
1982 "memory.grow",
1983 )?;
1984 state
1985 .operands
1986 .push(ValType::Num(crate::types::NumType::I32));
1987 }
1988 Instr::I32Const(_) => state
1989 .operands
1990 .push(ValType::Num(crate::types::NumType::I32)),
1991 Instr::I64Const(_) => state
1992 .operands
1993 .push(ValType::Num(crate::types::NumType::I64)),
1994 Instr::F32Const(_) => state
1995 .operands
1996 .push(ValType::Num(crate::types::NumType::F32)),
1997 Instr::F64Const(_) => state
1998 .operands
1999 .push(ValType::Num(crate::types::NumType::F64)),
2000 Instr::RefNull(ref_type) => {
2001 validate_reftype_type_indices(module, *ref_type, Some(function), offset)?;
2002 state
2003 .operands
2004 .push(normalize_valtype(module, ValType::Ref(*ref_type)));
2005 }
2006 Instr::RefIsNull => validate_ref_is_null(function, state, offset)?,
2007 Instr::RefAsNonNull => validate_ref_as_non_null(function, state, offset)?,
2008 Instr::RefFunc(idx) => {
2009 let type_idx = resolve_func_type_idx(module, *idx, function, offset)?;
2010 if !is_declared_function_ref(module, *idx) {
2011 return Err(ValidationError {
2012 offset: ByteOffset(offset),
2013 function: Some(function),
2014 kind: ValidationErrorKind::UndeclaredFuncRef { idx: *idx },
2015 });
2016 }
2017 state
2018 .operands
2019 .push(ValType::Ref(RefType::concrete(false, type_idx)));
2020 }
2021 Instr::V128Const(_) => state
2022 .operands
2023 .push(ValType::Vec(crate::types::VecType::V128)),
2024 Instr::I8x16Splat => validate_numeric_unary(
2025 function,
2026 state,
2027 offset,
2028 "i8x16.splat",
2029 ValType::Num(crate::types::NumType::I32),
2030 ValType::Vec(crate::types::VecType::V128),
2031 )?,
2032 Instr::I16x8Splat => validate_numeric_unary(
2033 function,
2034 state,
2035 offset,
2036 "i16x8.splat",
2037 ValType::Num(crate::types::NumType::I32),
2038 ValType::Vec(crate::types::VecType::V128),
2039 )?,
2040 Instr::I32x4Splat => validate_numeric_unary(
2041 function,
2042 state,
2043 offset,
2044 "i32x4.splat",
2045 ValType::Num(crate::types::NumType::I32),
2046 ValType::Vec(crate::types::VecType::V128),
2047 )?,
2048 Instr::I64x2Splat => validate_numeric_unary(
2049 function,
2050 state,
2051 offset,
2052 "i64x2.splat",
2053 ValType::Num(crate::types::NumType::I64),
2054 ValType::Vec(crate::types::VecType::V128),
2055 )?,
2056 Instr::F32x4Splat => validate_numeric_unary(
2057 function,
2058 state,
2059 offset,
2060 "f32x4.splat",
2061 ValType::Num(crate::types::NumType::F32),
2062 ValType::Vec(crate::types::VecType::V128),
2063 )?,
2064 Instr::F64x2Splat => validate_numeric_unary(
2065 function,
2066 state,
2067 offset,
2068 "f64x2.splat",
2069 ValType::Num(crate::types::NumType::F64),
2070 ValType::Vec(crate::types::VecType::V128),
2071 )?,
2072 Instr::I32x4ExtractLane(_) => validate_numeric_unary(
2073 function,
2074 state,
2075 offset,
2076 "i32x4.extract_lane",
2077 ValType::Vec(crate::types::VecType::V128),
2078 ValType::Num(crate::types::NumType::I32),
2079 )?,
2080 Instr::F32x4ExtractLane(_) => validate_numeric_unary(
2081 function,
2082 state,
2083 offset,
2084 "f32x4.extract_lane",
2085 ValType::Vec(crate::types::VecType::V128),
2086 ValType::Num(crate::types::NumType::F32),
2087 )?,
2088 Instr::I32x4ReplaceLane(_) => {
2089 pop_expect(
2090 function,
2091 state,
2092 ValType::Num(crate::types::NumType::I32),
2093 offset,
2094 "i32x4.replace_lane",
2095 )?;
2096 pop_expect(
2097 function,
2098 state,
2099 ValType::Vec(crate::types::VecType::V128),
2100 offset,
2101 "i32x4.replace_lane",
2102 )?;
2103 state
2104 .operands
2105 .push(ValType::Vec(crate::types::VecType::V128));
2106 }
2107 Instr::F32x4ReplaceLane(_) => {
2108 pop_expect(
2109 function,
2110 state,
2111 ValType::Num(crate::types::NumType::F32),
2112 offset,
2113 "f32x4.replace_lane",
2114 )?;
2115 pop_expect(
2116 function,
2117 state,
2118 ValType::Vec(crate::types::VecType::V128),
2119 offset,
2120 "f32x4.replace_lane",
2121 )?;
2122 state
2123 .operands
2124 .push(ValType::Vec(crate::types::VecType::V128));
2125 }
2126 Instr::V128Not => validate_numeric_unary(
2127 function,
2128 state,
2129 offset,
2130 "v128.not",
2131 ValType::Vec(crate::types::VecType::V128),
2132 ValType::Vec(crate::types::VecType::V128),
2133 )?,
2134 Instr::V128And | Instr::V128Or | Instr::V128Xor => validate_numeric_binary(
2135 function,
2136 state,
2137 offset,
2138 "v128.bitwise",
2139 ValType::Vec(crate::types::VecType::V128),
2140 ValType::Vec(crate::types::VecType::V128),
2141 )?,
2142 Instr::I8x16Add
2143 | Instr::I8x16Sub
2144 | Instr::I16x8Add
2145 | Instr::I16x8Sub
2146 | Instr::I32x4Add
2147 | Instr::I32x4Sub
2148 | Instr::I32x4Mul
2149 | Instr::I64x2Add
2150 | Instr::I64x2Sub
2151 | Instr::F32x4Add
2152 | Instr::F32x4Sub
2153 | Instr::F32x4Mul
2154 | Instr::F32x4Div
2155 | Instr::F64x2Add
2156 | Instr::F64x2Sub
2157 | Instr::F64x2Mul
2158 | Instr::F64x2Div => validate_numeric_binary(
2159 function,
2160 state,
2161 offset,
2162 "simd.arithmetic",
2163 ValType::Vec(crate::types::VecType::V128),
2164 ValType::Vec(crate::types::VecType::V128),
2165 )?,
2166 Instr::I32Eqz => validate_numeric_unary(
2167 function,
2168 state,
2169 offset,
2170 "i32.eqz",
2171 ValType::Num(crate::types::NumType::I32),
2172 ValType::Num(crate::types::NumType::I32),
2173 )?,
2174 Instr::I32Eq
2175 | Instr::I32Ne
2176 | Instr::I32LtS
2177 | Instr::I32LtU
2178 | Instr::I32GtS
2179 | Instr::I32GtU
2180 | Instr::I32LeS
2181 | Instr::I32LeU
2182 | Instr::I32GeS
2183 | Instr::I32GeU => validate_numeric_binary(
2184 function,
2185 state,
2186 offset,
2187 "i32.compare",
2188 ValType::Num(crate::types::NumType::I32),
2189 ValType::Num(crate::types::NumType::I32),
2190 )?,
2191 Instr::I64Eqz => validate_numeric_unary(
2192 function,
2193 state,
2194 offset,
2195 "i64.eqz",
2196 ValType::Num(crate::types::NumType::I64),
2197 ValType::Num(crate::types::NumType::I32),
2198 )?,
2199 Instr::I64Eq
2200 | Instr::I64Ne
2201 | Instr::I64LtS
2202 | Instr::I64LtU
2203 | Instr::I64GtS
2204 | Instr::I64GtU
2205 | Instr::I64LeS
2206 | Instr::I64LeU
2207 | Instr::I64GeS
2208 | Instr::I64GeU => validate_numeric_binary(
2209 function,
2210 state,
2211 offset,
2212 "i64.compare",
2213 ValType::Num(crate::types::NumType::I64),
2214 ValType::Num(crate::types::NumType::I32),
2215 )?,
2216 Instr::F32Eq | Instr::F32Ne | Instr::F32Lt | Instr::F32Gt | Instr::F32Le | Instr::F32Ge => {
2217 validate_numeric_binary(
2218 function,
2219 state,
2220 offset,
2221 "f32.compare",
2222 ValType::Num(crate::types::NumType::F32),
2223 ValType::Num(crate::types::NumType::I32),
2224 )?
2225 }
2226 Instr::F64Eq | Instr::F64Ne | Instr::F64Lt | Instr::F64Gt | Instr::F64Le | Instr::F64Ge => {
2227 validate_numeric_binary(
2228 function,
2229 state,
2230 offset,
2231 "f64.compare",
2232 ValType::Num(crate::types::NumType::F64),
2233 ValType::Num(crate::types::NumType::I32),
2234 )?
2235 }
2236 Instr::I32Clz | Instr::I32Ctz | Instr::I32Popcnt => validate_numeric_unary(
2237 function,
2238 state,
2239 offset,
2240 "i32.unary",
2241 ValType::Num(crate::types::NumType::I32),
2242 ValType::Num(crate::types::NumType::I32),
2243 )?,
2244 Instr::I32Add
2245 | Instr::I32Sub
2246 | Instr::I32Mul
2247 | Instr::I32DivS
2248 | Instr::I32DivU
2249 | Instr::I32RemS
2250 | Instr::I32RemU
2251 | Instr::I32And
2252 | Instr::I32Or
2253 | Instr::I32Xor
2254 | Instr::I32Shl
2255 | Instr::I32ShrS
2256 | Instr::I32ShrU
2257 | Instr::I32Rotl
2258 | Instr::I32Rotr => validate_numeric_binary(
2259 function,
2260 state,
2261 offset,
2262 "i32.binary",
2263 ValType::Num(crate::types::NumType::I32),
2264 ValType::Num(crate::types::NumType::I32),
2265 )?,
2266 Instr::I64Clz | Instr::I64Ctz | Instr::I64Popcnt => validate_numeric_unary(
2267 function,
2268 state,
2269 offset,
2270 "i64.unary",
2271 ValType::Num(crate::types::NumType::I64),
2272 ValType::Num(crate::types::NumType::I64),
2273 )?,
2274 Instr::I64Add
2275 | Instr::I64Sub
2276 | Instr::I64Mul
2277 | Instr::I64DivS
2278 | Instr::I64DivU
2279 | Instr::I64RemS
2280 | Instr::I64RemU
2281 | Instr::I64And
2282 | Instr::I64Or
2283 | Instr::I64Xor
2284 | Instr::I64Shl
2285 | Instr::I64ShrS
2286 | Instr::I64ShrU
2287 | Instr::I64Rotl
2288 | Instr::I64Rotr => validate_numeric_binary(
2289 function,
2290 state,
2291 offset,
2292 "i64.binary",
2293 ValType::Num(crate::types::NumType::I64),
2294 ValType::Num(crate::types::NumType::I64),
2295 )?,
2296 Instr::F32Abs
2297 | Instr::F32Neg
2298 | Instr::F32Ceil
2299 | Instr::F32Floor
2300 | Instr::F32Trunc
2301 | Instr::F32Nearest
2302 | Instr::F32Sqrt => validate_numeric_unary(
2303 function,
2304 state,
2305 offset,
2306 "f32.unary",
2307 ValType::Num(crate::types::NumType::F32),
2308 ValType::Num(crate::types::NumType::F32),
2309 )?,
2310 Instr::F32Add
2311 | Instr::F32Sub
2312 | Instr::F32Mul
2313 | Instr::F32Div
2314 | Instr::F32Min
2315 | Instr::F32Max
2316 | Instr::F32Copysign => validate_numeric_binary(
2317 function,
2318 state,
2319 offset,
2320 "f32.binary",
2321 ValType::Num(crate::types::NumType::F32),
2322 ValType::Num(crate::types::NumType::F32),
2323 )?,
2324 Instr::F64Abs
2325 | Instr::F64Neg
2326 | Instr::F64Ceil
2327 | Instr::F64Floor
2328 | Instr::F64Trunc
2329 | Instr::F64Nearest
2330 | Instr::F64Sqrt => validate_numeric_unary(
2331 function,
2332 state,
2333 offset,
2334 "f64.unary",
2335 ValType::Num(crate::types::NumType::F64),
2336 ValType::Num(crate::types::NumType::F64),
2337 )?,
2338 Instr::F64Add
2339 | Instr::F64Sub
2340 | Instr::F64Mul
2341 | Instr::F64Div
2342 | Instr::F64Min
2343 | Instr::F64Max
2344 | Instr::F64Copysign => validate_numeric_binary(
2345 function,
2346 state,
2347 offset,
2348 "f64.binary",
2349 ValType::Num(crate::types::NumType::F64),
2350 ValType::Num(crate::types::NumType::F64),
2351 )?,
2352 Instr::I32WrapI64 => validate_numeric_conversion(
2353 function,
2354 state,
2355 offset,
2356 "i32.wrap_i64",
2357 ValType::Num(crate::types::NumType::I64),
2358 ValType::Num(crate::types::NumType::I32),
2359 )?,
2360 Instr::I32TruncF32S | Instr::I32TruncF32U => validate_numeric_conversion(
2361 function,
2362 state,
2363 offset,
2364 "i32.trunc_f32",
2365 ValType::Num(crate::types::NumType::F32),
2366 ValType::Num(crate::types::NumType::I32),
2367 )?,
2368 Instr::I32TruncF64S | Instr::I32TruncF64U => validate_numeric_conversion(
2369 function,
2370 state,
2371 offset,
2372 "i32.trunc_f64",
2373 ValType::Num(crate::types::NumType::F64),
2374 ValType::Num(crate::types::NumType::I32),
2375 )?,
2376 Instr::I64ExtendI32S | Instr::I64ExtendI32U => validate_numeric_conversion(
2377 function,
2378 state,
2379 offset,
2380 "i64.extend_i32",
2381 ValType::Num(crate::types::NumType::I32),
2382 ValType::Num(crate::types::NumType::I64),
2383 )?,
2384 Instr::I64TruncF32S | Instr::I64TruncF32U => validate_numeric_conversion(
2385 function,
2386 state,
2387 offset,
2388 "i64.trunc_f32",
2389 ValType::Num(crate::types::NumType::F32),
2390 ValType::Num(crate::types::NumType::I64),
2391 )?,
2392 Instr::I64TruncF64S | Instr::I64TruncF64U => validate_numeric_conversion(
2393 function,
2394 state,
2395 offset,
2396 "i64.trunc_f64",
2397 ValType::Num(crate::types::NumType::F64),
2398 ValType::Num(crate::types::NumType::I64),
2399 )?,
2400 Instr::F32ConvertI32S | Instr::F32ConvertI32U => validate_numeric_conversion(
2401 function,
2402 state,
2403 offset,
2404 "f32.convert_i32",
2405 ValType::Num(crate::types::NumType::I32),
2406 ValType::Num(crate::types::NumType::F32),
2407 )?,
2408 Instr::F32ConvertI64S | Instr::F32ConvertI64U => validate_numeric_conversion(
2409 function,
2410 state,
2411 offset,
2412 "f32.convert_i64",
2413 ValType::Num(crate::types::NumType::I64),
2414 ValType::Num(crate::types::NumType::F32),
2415 )?,
2416 Instr::F32DemoteF64 => validate_numeric_conversion(
2417 function,
2418 state,
2419 offset,
2420 "f32.demote_f64",
2421 ValType::Num(crate::types::NumType::F64),
2422 ValType::Num(crate::types::NumType::F32),
2423 )?,
2424 Instr::F64ConvertI32S | Instr::F64ConvertI32U => validate_numeric_conversion(
2425 function,
2426 state,
2427 offset,
2428 "f64.convert_i32",
2429 ValType::Num(crate::types::NumType::I32),
2430 ValType::Num(crate::types::NumType::F64),
2431 )?,
2432 Instr::F64ConvertI64S | Instr::F64ConvertI64U => validate_numeric_conversion(
2433 function,
2434 state,
2435 offset,
2436 "f64.convert_i64",
2437 ValType::Num(crate::types::NumType::I64),
2438 ValType::Num(crate::types::NumType::F64),
2439 )?,
2440 Instr::F64PromoteF32 => validate_numeric_conversion(
2441 function,
2442 state,
2443 offset,
2444 "f64.promote_f32",
2445 ValType::Num(crate::types::NumType::F32),
2446 ValType::Num(crate::types::NumType::F64),
2447 )?,
2448 Instr::I32ReinterpretF32 => validate_numeric_conversion(
2449 function,
2450 state,
2451 offset,
2452 "i32.reinterpret_f32",
2453 ValType::Num(crate::types::NumType::F32),
2454 ValType::Num(crate::types::NumType::I32),
2455 )?,
2456 Instr::I64ReinterpretF64 => validate_numeric_conversion(
2457 function,
2458 state,
2459 offset,
2460 "i64.reinterpret_f64",
2461 ValType::Num(crate::types::NumType::F64),
2462 ValType::Num(crate::types::NumType::I64),
2463 )?,
2464 Instr::F32ReinterpretI32 => validate_numeric_conversion(
2465 function,
2466 state,
2467 offset,
2468 "f32.reinterpret_i32",
2469 ValType::Num(crate::types::NumType::I32),
2470 ValType::Num(crate::types::NumType::F32),
2471 )?,
2472 Instr::F64ReinterpretI64 => validate_numeric_conversion(
2473 function,
2474 state,
2475 offset,
2476 "f64.reinterpret_i64",
2477 ValType::Num(crate::types::NumType::I64),
2478 ValType::Num(crate::types::NumType::F64),
2479 )?,
2480 Instr::I32Extend8S | Instr::I32Extend16S => validate_numeric_conversion(
2481 function,
2482 state,
2483 offset,
2484 "i32.sign_extend",
2485 ValType::Num(crate::types::NumType::I32),
2486 ValType::Num(crate::types::NumType::I32),
2487 )?,
2488 Instr::I64Extend8S | Instr::I64Extend16S | Instr::I64Extend32S => {
2489 validate_numeric_conversion(
2490 function,
2491 state,
2492 offset,
2493 "i64.sign_extend",
2494 ValType::Num(crate::types::NumType::I64),
2495 ValType::Num(crate::types::NumType::I64),
2496 )?
2497 }
2498 Instr::I32TruncSatF32S | Instr::I32TruncSatF32U => validate_numeric_conversion(
2499 function,
2500 state,
2501 offset,
2502 "i32.trunc_sat_f32",
2503 ValType::Num(crate::types::NumType::F32),
2504 ValType::Num(crate::types::NumType::I32),
2505 )?,
2506 Instr::I32TruncSatF64S | Instr::I32TruncSatF64U => validate_numeric_conversion(
2507 function,
2508 state,
2509 offset,
2510 "i32.trunc_sat_f64",
2511 ValType::Num(crate::types::NumType::F64),
2512 ValType::Num(crate::types::NumType::I32),
2513 )?,
2514 Instr::I64TruncSatF32S | Instr::I64TruncSatF32U => validate_numeric_conversion(
2515 function,
2516 state,
2517 offset,
2518 "i64.trunc_sat_f32",
2519 ValType::Num(crate::types::NumType::F32),
2520 ValType::Num(crate::types::NumType::I64),
2521 )?,
2522 Instr::I64TruncSatF64S | Instr::I64TruncSatF64U => validate_numeric_conversion(
2523 function,
2524 state,
2525 offset,
2526 "i64.trunc_sat_f64",
2527 ValType::Num(crate::types::NumType::F64),
2528 ValType::Num(crate::types::NumType::I64),
2529 )?,
2530 }
2531
2532 Ok(())
2533}
2534
2535fn validate_numeric_unary(
2536 function: FuncIdx,
2537 state: &mut ValidationState,
2538 offset: usize,
2539 op: &'static str,
2540 input: ValType,
2541 result: ValType,
2542) -> Result<(), ValidationError> {
2543 pop_expect(function, state, input, offset, op)?;
2544 state.operands.push(result);
2545 Ok(())
2546}
2547
2548fn validate_numeric_binary(
2549 function: FuncIdx,
2550 state: &mut ValidationState,
2551 offset: usize,
2552 op: &'static str,
2553 input: ValType,
2554 result: ValType,
2555) -> Result<(), ValidationError> {
2556 pop_expect(function, state, input, offset, op)?;
2557 pop_expect(function, state, input, offset, op)?;
2558 state.operands.push(result);
2559 Ok(())
2560}
2561
2562fn validate_numeric_conversion(
2563 function: FuncIdx,
2564 state: &mut ValidationState,
2565 offset: usize,
2566 op: &'static str,
2567 input: ValType,
2568 result: ValType,
2569) -> Result<(), ValidationError> {
2570 pop_expect(function, state, input, offset, op)?;
2571 state.operands.push(result);
2572 Ok(())
2573}
2574
2575fn validate_ref_is_null(
2576 function: FuncIdx,
2577 state: &mut ValidationState,
2578 offset: usize,
2579) -> Result<(), ValidationError> {
2580 let _ = pop_ref_type(function, state, offset, "ref.is_null")?;
2581 state
2582 .operands
2583 .push(ValType::Num(crate::types::NumType::I32));
2584 Ok(())
2585}
2586
2587fn validate_ref_as_non_null(
2588 function: FuncIdx,
2589 state: &mut ValidationState,
2590 offset: usize,
2591) -> Result<(), ValidationError> {
2592 let found = pop_ref_type(function, state, offset, "ref.as_non_null")?;
2593 match found {
2594 Some(found) => state.operands.push(ValType::Ref(found.as_non_null())),
2595 None => state.operands.push_bottom(),
2596 }
2597 Ok(())
2598}
2599
2600struct MemLoadValidation {
2601 op: &'static str,
2602 memory: MemIdx,
2603 found_align: u32,
2604 max_align: u32,
2605 result: ValType,
2606}
2607
2608struct MemStoreValidation {
2609 op: &'static str,
2610 memory: MemIdx,
2611 found_align: u32,
2612 max_align: u32,
2613 stored: ValType,
2614}
2615
2616struct SimdLaneValidation {
2617 op: &'static str,
2618 memory: MemIdx,
2619 found_align: u32,
2620 max_align: u32,
2621 lane: u8,
2622 max_lane: u8,
2623}
2624
2625fn validate_load(
2626 module: &Module<'_>,
2627 function: FuncIdx,
2628 state: &mut ValidationState,
2629 offset: usize,
2630 load: MemLoadValidation,
2631) -> Result<(), ValidationError> {
2632 validate_memarg_align(function, offset, load.op, load.found_align, load.max_align)?;
2633 resolve_memory_type(module, load.memory, function, offset)?;
2634 pop_expect(
2635 function,
2636 state,
2637 ValType::Num(crate::types::NumType::I32),
2638 offset,
2639 load.op,
2640 )?;
2641 state.operands.push(load.result);
2642 Ok(())
2643}
2644
2645fn validate_store(
2646 module: &Module<'_>,
2647 function: FuncIdx,
2648 state: &mut ValidationState,
2649 offset: usize,
2650 store: MemStoreValidation,
2651) -> Result<(), ValidationError> {
2652 validate_memarg_align(
2653 function,
2654 offset,
2655 store.op,
2656 store.found_align,
2657 store.max_align,
2658 )?;
2659 resolve_memory_type(module, store.memory, function, offset)?;
2660 pop_expect(function, state, store.stored, offset, store.op)?;
2661 pop_expect(
2662 function,
2663 state,
2664 ValType::Num(crate::types::NumType::I32),
2665 offset,
2666 store.op,
2667 )?;
2668 Ok(())
2669}
2670
2671fn validate_simd_load_lane(
2672 module: &Module<'_>,
2673 function: FuncIdx,
2674 state: &mut ValidationState,
2675 offset: usize,
2676 lane: SimdLaneValidation,
2677) -> Result<(), ValidationError> {
2678 validate_memarg_align(function, offset, lane.op, lane.found_align, lane.max_align)?;
2679 validate_simd_lane_idx(function, offset, lane.op, lane.lane, lane.max_lane)?;
2680 resolve_memory_type(module, lane.memory, function, offset)?;
2681 pop_expect(
2682 function,
2683 state,
2684 ValType::Vec(crate::types::VecType::V128),
2685 offset,
2686 lane.op,
2687 )?;
2688 pop_expect(
2689 function,
2690 state,
2691 ValType::Num(crate::types::NumType::I32),
2692 offset,
2693 lane.op,
2694 )?;
2695 state
2696 .operands
2697 .push(ValType::Vec(crate::types::VecType::V128));
2698 Ok(())
2699}
2700
2701fn validate_simd_store_lane(
2702 module: &Module<'_>,
2703 function: FuncIdx,
2704 state: &mut ValidationState,
2705 offset: usize,
2706 lane: SimdLaneValidation,
2707) -> Result<(), ValidationError> {
2708 validate_memarg_align(function, offset, lane.op, lane.found_align, lane.max_align)?;
2709 validate_simd_lane_idx(function, offset, lane.op, lane.lane, lane.max_lane)?;
2710 resolve_memory_type(module, lane.memory, function, offset)?;
2711 pop_expect(
2712 function,
2713 state,
2714 ValType::Vec(crate::types::VecType::V128),
2715 offset,
2716 lane.op,
2717 )?;
2718 pop_expect(
2719 function,
2720 state,
2721 ValType::Num(crate::types::NumType::I32),
2722 offset,
2723 lane.op,
2724 )?;
2725 Ok(())
2726}
2727
2728fn validate_memarg_align(
2729 function: FuncIdx,
2730 offset: usize,
2731 op: &'static str,
2732 found: u32,
2733 max: u32,
2734) -> Result<(), ValidationError> {
2735 if found > max {
2736 return Err(ValidationError {
2737 offset: ByteOffset(offset),
2738 function: Some(function),
2739 kind: ValidationErrorKind::InvalidMemArgAlign { op, max, found },
2740 });
2741 }
2742
2743 Ok(())
2744}
2745
2746fn validate_simd_lane_idx(
2747 function: FuncIdx,
2748 offset: usize,
2749 op: &'static str,
2750 found: u8,
2751 max: u8,
2752) -> Result<(), ValidationError> {
2753 if found > max {
2754 return Err(ValidationError {
2755 offset: ByteOffset(offset),
2756 function: Some(function),
2757 kind: ValidationErrorKind::InvalidSimdLaneIdx { op, max, found },
2758 });
2759 }
2760
2761 Ok(())
2762}
2763
2764fn resolve_block_type(
2765 module: &Module<'_>,
2766 function: FuncIdx,
2767 block_type: BlockType,
2768 offset: usize,
2769) -> Result<FuncType, ValidationError> {
2770 match block_type {
2771 BlockType::Empty => Ok(FuncType {
2772 params: Vec::new(),
2773 results: Vec::new(),
2774 }),
2775 BlockType::Val(val) => {
2776 validate_valtype_type_indices(module, val, Some(function), offset)?;
2777 Ok(FuncType {
2778 params: Vec::new(),
2779 results: vec![normalize_valtype(module, val)],
2780 })
2781 }
2782 BlockType::TypeIdx(idx) => module
2783 .types
2784 .get(idx as usize)
2785 .map(|ty| normalize_func_type(module, ty))
2786 .ok_or(ValidationError {
2787 offset: ByteOffset(offset),
2788 function: Some(function),
2789 kind: ValidationErrorKind::InvalidBlockType { block_type },
2790 }),
2791 }
2792}
2793
2794fn resolve_type(
2795 module: &Module<'_>,
2796 idx: TypeIdx,
2797 function: Option<FuncIdx>,
2798 offset: usize,
2799) -> Result<FuncType, ValidationError> {
2800 let idx = canonicalize_func_type_idx(module, idx);
2801 module
2802 .types
2803 .get(idx.0 as usize)
2804 .map(|ty| normalize_func_type(module, ty))
2805 .ok_or(ValidationError {
2806 offset: ByteOffset(offset),
2807 function,
2808 kind: ValidationErrorKind::UnknownTypeIdx { idx },
2809 })
2810}
2811
2812fn resolve_func_type(
2813 module: &Module<'_>,
2814 idx: FuncIdx,
2815 function: FuncIdx,
2816 offset: usize,
2817) -> Result<FuncType, ValidationError> {
2818 let type_idx = resolve_func_type_idx_with_context(module, idx, Some(function), offset)?;
2819 resolve_type(module, type_idx, Some(function), offset)
2820}
2821
2822fn contains_ref_func_expr(
2823 _module: &Module<'_>,
2824 expr: &[u8],
2825 offset: usize,
2826 target: FuncIdx,
2827) -> bool {
2828 decode_instr_sequence_with_offsets(expr, offset)
2829 .ok()
2830 .is_some_and(|instrs| {
2831 instrs
2832 .into_iter()
2833 .any(|instr| matches!(instr.instr, Instr::RefFunc(idx) if idx == target))
2834 })
2835}
2836
2837fn is_declared_function_ref(module: &Module<'_>, target: FuncIdx) -> bool {
2838 if module
2839 .exports()
2840 .iter()
2841 .any(|export| matches!(export.desc, ExportDesc::Func(idx) if idx == target))
2842 {
2843 return true;
2844 }
2845
2846 if module
2847 .globals()
2848 .iter()
2849 .any(|global| contains_ref_func_expr(module, global.init_expr, global.init_offset, target))
2850 {
2851 return true;
2852 }
2853
2854 if module.tables.iter().any(|table| {
2855 table
2856 .init
2857 .as_ref()
2858 .is_some_and(|init| contains_ref_func_expr(module, init, 0, target))
2859 }) {
2860 return true;
2861 }
2862
2863 module.elements().iter().any(|element| match &element.init {
2864 ElementInit::FuncIndices(funcs) => funcs.contains(&target),
2865 ElementInit::Expressions(exprs) => exprs
2866 .iter()
2867 .any(|expr| contains_ref_func_expr(module, expr.expr, expr.offset, target)),
2868 })
2869}
2870
2871fn resolve_func_type_idx_for_module(
2872 module: &Module<'_>,
2873 idx: FuncIdx,
2874 offset: usize,
2875) -> Result<TypeIdx, ValidationError> {
2876 resolve_func_type_idx_with_context(module, idx, None, offset)
2877 .map(|idx| canonicalize_func_type_idx(module, idx))
2878}
2879
2880fn resolve_func_type_idx(
2881 module: &Module<'_>,
2882 idx: FuncIdx,
2883 function: FuncIdx,
2884 offset: usize,
2885) -> Result<TypeIdx, ValidationError> {
2886 resolve_func_type_idx_with_context(module, idx, Some(function), offset)
2887 .map(|idx| canonicalize_func_type_idx(module, idx))
2888}
2889
2890fn resolve_func_type_for_module<'m>(
2891 module: &'m Module<'_>,
2892 idx: FuncIdx,
2893 offset: usize,
2894) -> Result<&'m FuncType, ValidationError> {
2895 resolve_func_type_with_context(module, idx, None, offset)
2896}
2897
2898fn resolve_func_type_with_context<'m>(
2899 module: &'m Module<'_>,
2900 idx: FuncIdx,
2901 function: Option<FuncIdx>,
2902 offset: usize,
2903) -> Result<&'m FuncType, ValidationError> {
2904 let type_idx = resolve_func_type_idx_with_context(module, idx, function, offset)?;
2905
2906 module
2907 .types
2908 .get(type_idx.0 as usize)
2909 .ok_or(ValidationError {
2910 offset: ByteOffset(offset),
2911 function,
2912 kind: ValidationErrorKind::UnknownTypeIdx { idx: type_idx },
2913 })
2914}
2915
2916fn resolve_func_type_idx_with_context(
2917 module: &Module<'_>,
2918 idx: FuncIdx,
2919 function: Option<FuncIdx>,
2920 offset: usize,
2921) -> Result<TypeIdx, ValidationError> {
2922 let imported_funcs = module
2923 .imports
2924 .iter()
2925 .filter_map(|import| match import.desc {
2926 ImportDesc::Func(type_idx) => Some(type_idx),
2927 _ => None,
2928 });
2929 let defined_funcs = module.functions.iter().copied();
2930
2931 imported_funcs
2932 .chain(defined_funcs)
2933 .nth(idx.0 as usize)
2934 .ok_or(ValidationError {
2935 offset: ByteOffset(offset),
2936 function,
2937 kind: ValidationErrorKind::UnknownFuncIdx { idx },
2938 })
2939}
2940
2941fn resolve_global_type(
2942 module: &Module<'_>,
2943 idx: GlobalIdx,
2944 function: FuncIdx,
2945 offset: usize,
2946) -> Result<crate::types::GlobalType, ValidationError> {
2947 resolve_global_type_with_context(module, idx, Some(function), offset)
2948}
2949
2950fn resolve_global_type_for_module(
2951 module: &Module<'_>,
2952 idx: GlobalIdx,
2953 offset: usize,
2954) -> Result<crate::types::GlobalType, ValidationError> {
2955 resolve_global_type_with_context(module, idx, None, offset)
2956}
2957
2958fn resolve_global_type_with_context(
2959 module: &Module<'_>,
2960 idx: GlobalIdx,
2961 function: Option<FuncIdx>,
2962 offset: usize,
2963) -> Result<crate::types::GlobalType, ValidationError> {
2964 let imported_count = module
2965 .imports
2966 .iter()
2967 .filter(|import| matches!(import.desc, ImportDesc::Global(_)))
2968 .count();
2969 let defined_count = module.globals.len();
2970 let available = (imported_count + defined_count) as u32;
2971
2972 let imported = module
2973 .imports
2974 .iter()
2975 .filter_map(|import| match import.desc {
2976 ImportDesc::Global(global) => Some(global),
2977 _ => None,
2978 });
2979 let defined = module.globals.iter().map(|global| global.global_type);
2980
2981 imported
2982 .chain(defined)
2983 .nth(idx.0 as usize)
2984 .map(|global| normalize_global_type(module, global))
2985 .ok_or(ValidationError {
2986 offset: ByteOffset(offset),
2987 function,
2988 kind: ValidationErrorKind::UnknownGlobalIdx { idx, available },
2989 })
2990}
2991
2992fn resolve_table_type_for_module(
2993 module: &Module<'_>,
2994 idx: TableIdx,
2995 offset: usize,
2996) -> Result<crate::types::TableType, ValidationError> {
2997 resolve_table_type_with_context(module, idx, None, offset)
2998}
2999
3000fn resolve_table_type_with_context(
3001 module: &Module<'_>,
3002 idx: TableIdx,
3003 function: Option<FuncIdx>,
3004 offset: usize,
3005) -> Result<crate::types::TableType, ValidationError> {
3006 let imported_count = module
3007 .imports
3008 .iter()
3009 .filter(|import| matches!(import.desc, ImportDesc::Table(_)))
3010 .count();
3011 let defined_count = module.tables.len();
3012 let available = (imported_count + defined_count) as u32;
3013
3014 let imported = module
3015 .imports
3016 .iter()
3017 .filter_map(|import| match &import.desc {
3018 ImportDesc::Table(table) => Some(table),
3019 _ => None,
3020 });
3021 let defined = module.tables.iter();
3022
3023 imported
3024 .chain(defined)
3025 .nth(idx.0 as usize)
3026 .map(|table| normalize_table_type(module, table.clone()))
3027 .ok_or(ValidationError {
3028 offset: ByteOffset(offset),
3029 function,
3030 kind: ValidationErrorKind::UnknownTableIdx { idx, available },
3031 })
3032}
3033
3034fn resolve_data_segment<'a>(
3035 module: &'a Module<'a>,
3036 idx: DataIdx,
3037 function: FuncIdx,
3038 offset: usize,
3039) -> Result<&'a crate::types::DataSegment<'a>, ValidationError> {
3040 let available = module.data().len() as u32;
3041 module.data().get(idx.0 as usize).ok_or(ValidationError {
3042 offset: ByteOffset(offset),
3043 function: Some(function),
3044 kind: ValidationErrorKind::UnknownDataIdx { idx, available },
3045 })
3046}
3047
3048fn resolve_element_segment<'a>(
3049 module: &'a Module<'a>,
3050 idx: ElemIdx,
3051 function: FuncIdx,
3052 offset: usize,
3053) -> Result<&'a crate::types::ElementSegment<'a>, ValidationError> {
3054 let available = module.elements().len() as u32;
3055 module
3056 .elements()
3057 .get(idx.0 as usize)
3058 .ok_or(ValidationError {
3059 offset: ByteOffset(offset),
3060 function: Some(function),
3061 kind: ValidationErrorKind::UnknownElemIdx { idx, available },
3062 })
3063}
3064
3065fn resolve_memory_type(
3066 module: &Module<'_>,
3067 idx: MemIdx,
3068 function: FuncIdx,
3069 offset: usize,
3070) -> Result<crate::types::MemType, ValidationError> {
3071 resolve_memory_type_with_context(module, idx, Some(function), offset)
3072}
3073
3074fn resolve_memory_type_for_module(
3075 module: &Module<'_>,
3076 idx: MemIdx,
3077 offset: usize,
3078) -> Result<crate::types::MemType, ValidationError> {
3079 resolve_memory_type_with_context(module, idx, None, offset)
3080}
3081
3082fn resolve_memory_type_with_context(
3083 module: &Module<'_>,
3084 idx: MemIdx,
3085 function: Option<FuncIdx>,
3086 offset: usize,
3087) -> Result<crate::types::MemType, ValidationError> {
3088 let imported_count = module
3089 .imports
3090 .iter()
3091 .filter(|import| matches!(import.desc, ImportDesc::Mem(_)))
3092 .count();
3093 let defined_count = module.memories.len();
3094 let available = (imported_count + defined_count) as u32;
3095
3096 let imported = module
3097 .imports
3098 .iter()
3099 .filter_map(|import| match import.desc {
3100 ImportDesc::Mem(memory) => Some(memory),
3101 _ => None,
3102 });
3103 let defined = module.memories.iter().copied();
3104
3105 imported
3106 .chain(defined)
3107 .nth(idx.0 as usize)
3108 .ok_or(ValidationError {
3109 offset: ByteOffset(offset),
3110 function,
3111 kind: ValidationErrorKind::UnknownMemIdx { idx, available },
3112 })
3113}
3114
3115fn validate_label(
3116 function: FuncIdx,
3117 state: &ValidationState,
3118 label: crate::types::LabelIdx,
3119 offset: usize,
3120) -> Result<&[ValType], ValidationError> {
3121 state.current_label_types(label.0).ok_or(ValidationError {
3122 offset: ByteOffset(offset),
3123 function: Some(function),
3124 kind: ValidationErrorKind::UnknownLabelIdx { idx: label },
3125 })
3126}
3127
3128fn finish_frame(
3129 function: FuncIdx,
3130 state: &mut ValidationState,
3131 offset: usize,
3132) -> Result<(), ValidationError> {
3133 let frame = state.current_frame().clone();
3134
3135 if frame.kind == Function {
3136 return Err(ValidationError {
3137 offset: ByteOffset(offset),
3138 function: Some(function),
3139 kind: ValidationErrorKind::UnexpectedEnd,
3140 });
3141 }
3142
3143 if frame.kind == If && !frame.has_else && frame.start_types != frame.end_types {
3146 return Err(ValidationError {
3147 offset: ByteOffset(offset),
3148 function: Some(function),
3149 kind: ValidationErrorKind::MissingElseForResult,
3150 });
3151 }
3152
3153 if let Err(found) = ensure_frame_end_types(state, frame.outer_height, &frame.end_types) {
3154 return Err(ValidationError {
3155 offset: ByteOffset(offset),
3156 function: Some(function),
3157 kind: ValidationErrorKind::ControlResultTypeMismatch {
3158 expected: frame.end_types.clone(),
3159 found,
3160 },
3161 });
3162 }
3163
3164 pop_control_result_types(function, state, &frame.end_types, offset)?;
3165 let _closed = state.pop_frame().ok_or(ValidationError {
3166 offset: ByteOffset(offset),
3167 function: Some(function),
3168 kind: ValidationErrorKind::UnexpectedEnd,
3169 })?;
3170 state.operands.truncate(frame.outer_height);
3171 state.local_inits = frame.local_inits;
3172 for ty in frame.end_types {
3173 state.operands.push(ty);
3174 }
3175 state.reachability = Reachability::Reachable;
3176 Ok(())
3177}
3178
3179fn canonicalize_func_type_idx(module: &Module<'_>, idx: TypeIdx) -> TypeIdx {
3180 if module.types.get(idx.0 as usize).is_none() {
3181 return idx;
3182 }
3183
3184 for candidate in 0..idx.0 {
3185 let candidate = TypeIdx(candidate);
3186 if func_type_indices_equivalent(module, candidate, idx) {
3187 return candidate;
3188 }
3189 }
3190
3191 idx
3192}
3193
3194fn func_type_indices_equivalent(module: &Module<'_>, lhs: TypeIdx, rhs: TypeIdx) -> bool {
3195 let mut seen = BTreeSet::new();
3196 func_type_indices_equivalent_inner(module, lhs, rhs, &mut seen)
3197}
3198
3199fn func_type_indices_equivalent_inner(
3200 module: &Module<'_>,
3201 lhs: TypeIdx,
3202 rhs: TypeIdx,
3203 seen: &mut BTreeSet<(u32, u32)>,
3204) -> bool {
3205 let key = if lhs.0 <= rhs.0 {
3206 (lhs.0, rhs.0)
3207 } else {
3208 (rhs.0, lhs.0)
3209 };
3210 if !seen.insert(key) {
3211 return true;
3212 }
3213
3214 let Some(lhs_ty) = module.types.get(lhs.0 as usize) else {
3215 return false;
3216 };
3217 let Some(rhs_ty) = module.types.get(rhs.0 as usize) else {
3218 return false;
3219 };
3220
3221 lhs_ty.params.len() == rhs_ty.params.len()
3222 && lhs_ty.results.len() == rhs_ty.results.len()
3223 && lhs_ty
3224 .params
3225 .iter()
3226 .zip(&rhs_ty.params)
3227 .all(|(lhs, rhs)| valtype_equivalent_inner(module, *lhs, *rhs, seen))
3228 && lhs_ty
3229 .results
3230 .iter()
3231 .zip(&rhs_ty.results)
3232 .all(|(lhs, rhs)| valtype_equivalent_inner(module, *lhs, *rhs, seen))
3233}
3234
3235fn valtype_equivalent_inner(
3236 module: &Module<'_>,
3237 lhs: ValType,
3238 rhs: ValType,
3239 seen: &mut BTreeSet<(u32, u32)>,
3240) -> bool {
3241 match (lhs, rhs) {
3242 (ValType::Ref(lhs), ValType::Ref(rhs)) => reftype_equivalent_inner(module, lhs, rhs, seen),
3243 _ => lhs == rhs,
3244 }
3245}
3246
3247fn reftype_equivalent_inner(
3248 module: &Module<'_>,
3249 lhs: RefType,
3250 rhs: RefType,
3251 seen: &mut BTreeSet<(u32, u32)>,
3252) -> bool {
3253 lhs.is_nullable() == rhs.is_nullable()
3254 && match (lhs.heap_type(), rhs.heap_type()) {
3255 (crate::types::HeapType::Type(lhs), crate::types::HeapType::Type(rhs)) => {
3256 func_type_indices_equivalent_inner(module, lhs, rhs, seen)
3257 }
3258 (lhs, rhs) => lhs == rhs,
3259 }
3260}
3261
3262fn validate_func_type_definition_type_indices(
3263 module: &Module<'_>,
3264 current_type: TypeIdx,
3265 ty: &FuncType,
3266 offset: usize,
3267) -> Result<(), ValidationError> {
3268 for ¶m in &ty.params {
3269 validate_valtype_type_indices_in_type_definition(module, current_type, param, offset)?;
3270 }
3271 for &result in &ty.results {
3272 validate_valtype_type_indices_in_type_definition(module, current_type, result, offset)?;
3273 }
3274 Ok(())
3275}
3276
3277fn validate_valtype_type_indices(
3278 module: &Module<'_>,
3279 ty: ValType,
3280 function: Option<FuncIdx>,
3281 offset: usize,
3282) -> Result<(), ValidationError> {
3283 if let ValType::Ref(ref_type) = ty {
3284 validate_reftype_type_indices(module, ref_type, function, offset)?;
3285 }
3286 Ok(())
3287}
3288
3289fn validate_valtype_type_indices_in_type_definition(
3290 module: &Module<'_>,
3291 current_type: TypeIdx,
3292 ty: ValType,
3293 offset: usize,
3294) -> Result<(), ValidationError> {
3295 if let ValType::Ref(ref_type) = ty {
3296 validate_reftype_type_indices_in_type_definition(module, current_type, ref_type, offset)?;
3297 }
3298 Ok(())
3299}
3300
3301fn validate_reftype_type_indices(
3302 module: &Module<'_>,
3303 ty: RefType,
3304 function: Option<FuncIdx>,
3305 offset: usize,
3306) -> Result<(), ValidationError> {
3307 if let crate::types::HeapType::Type(idx) = ty.heap_type()
3308 && module.types.get(idx.0 as usize).is_none()
3309 {
3310 return Err(ValidationError {
3311 offset: ByteOffset(offset),
3312 function,
3313 kind: ValidationErrorKind::UnknownTypeIdx { idx },
3314 });
3315 }
3316
3317 Ok(())
3318}
3319
3320fn validate_reftype_type_indices_in_type_definition(
3321 module: &Module<'_>,
3322 current_type: TypeIdx,
3323 ty: RefType,
3324 offset: usize,
3325) -> Result<(), ValidationError> {
3326 if let crate::types::HeapType::Type(idx) = ty.heap_type()
3327 && (idx.0 > current_type.0 || module.types.get(idx.0 as usize).is_none())
3328 {
3329 return Err(ValidationError {
3330 offset: ByteOffset(offset),
3331 function: None,
3332 kind: ValidationErrorKind::UnknownTypeIdx { idx },
3333 });
3334 }
3335
3336 Ok(())
3337}
3338
3339fn normalize_reftype(module: &Module<'_>, ty: RefType) -> RefType {
3340 match ty.heap_type() {
3341 crate::types::HeapType::Type(idx) => RefType::from_parts(
3342 ty.is_nullable(),
3343 crate::types::HeapType::Type(canonicalize_func_type_idx(module, idx)),
3344 ),
3345 _ => ty,
3346 }
3347}
3348
3349fn normalize_valtype(module: &Module<'_>, ty: ValType) -> ValType {
3350 match ty {
3351 ValType::Ref(ref_type) => ValType::Ref(normalize_reftype(module, ref_type)),
3352 _ => ty,
3353 }
3354}
3355
3356fn normalize_func_type(module: &Module<'_>, ty: &FuncType) -> FuncType {
3357 FuncType {
3358 params: ty
3359 .params
3360 .iter()
3361 .copied()
3362 .map(|ty| normalize_valtype(module, ty))
3363 .collect(),
3364 results: ty
3365 .results
3366 .iter()
3367 .copied()
3368 .map(|ty| normalize_valtype(module, ty))
3369 .collect(),
3370 }
3371}
3372
3373fn normalize_global_type(
3374 module: &Module<'_>,
3375 ty: crate::types::GlobalType,
3376) -> crate::types::GlobalType {
3377 crate::types::GlobalType {
3378 val_type: normalize_valtype(module, ty.val_type),
3379 mutability: ty.mutability,
3380 }
3381}
3382
3383fn normalize_table_type(
3384 module: &Module<'_>,
3385 ty: crate::types::TableType,
3386) -> crate::types::TableType {
3387 crate::types::TableType {
3388 elem: normalize_reftype(module, ty.elem),
3389 limits: ty.limits,
3390 init: ty.init.clone(),
3391 }
3392}
3393
3394fn reftype_matches(found: RefType, expected: RefType) -> bool {
3395 found.is_subtype_of(expected)
3396}
3397
3398fn valtype_matches(found: ValType, expected: ValType) -> bool {
3399 found.is_subtype_of(expected)
3400}
3401
3402fn valtype_vec_matches(found: &[ValType], expected: &[ValType]) -> bool {
3403 found.len() == expected.len()
3404 && found
3405 .iter()
3406 .zip(expected)
3407 .all(|(found, expected)| valtype_matches(*found, *expected))
3408}
3409
3410fn is_stack_polymorphic(state: &ValidationState) -> bool {
3411 state.reachability == Reachability::Unreachable
3412 && state.operands.len() == state.current_frame().outer_height
3413}
3414
3415fn operand_matches(found: OperandType, expected: ValType) -> bool {
3416 match found {
3417 OperandType::Typed(found) => valtype_matches(found, expected),
3418 OperandType::Bottom => true,
3419 }
3420}
3421
3422fn operand_to_valtype(found: OperandType, fallback: ValType) -> ValType {
3423 match found {
3424 OperandType::Typed(found) => found,
3425 OperandType::Bottom => fallback,
3426 }
3427}
3428
3429fn concrete_stack(state: &ValidationState) -> Vec<ValType> {
3430 state
3431 .operands
3432 .as_slice()
3433 .iter()
3434 .filter_map(|operand| match operand {
3435 OperandType::Typed(ty) => Some(*ty),
3436 OperandType::Bottom => None,
3437 })
3438 .collect()
3439}
3440
3441fn stack_found(actual: &[OperandType], expected: &[ValType]) -> Vec<ValType> {
3442 let expected_start = expected.len().saturating_sub(actual.len());
3443 actual
3444 .iter()
3445 .enumerate()
3446 .filter_map(|(idx, operand)| match operand {
3447 OperandType::Typed(ty) => Some(*ty),
3448 OperandType::Bottom => expected.get(expected_start + idx).copied(),
3449 })
3450 .collect()
3451}
3452
3453fn ensure_frame_end_types(
3454 state: &ValidationState,
3455 outer_height: usize,
3456 expected: &[ValType],
3457) -> Result<(), Vec<ValType>> {
3458 let operands = state.operands.as_slice();
3459 if operands.len() < outer_height {
3460 return Err(Vec::new());
3461 }
3462 let actual = &operands[outer_height..];
3463 let found = stack_found(actual, expected);
3464
3465 if actual.len() > expected.len() {
3466 return Err(found);
3467 }
3468
3469 let expected_suffix = &expected[expected.len().saturating_sub(actual.len())..];
3470 if actual
3471 .iter()
3472 .zip(expected_suffix)
3473 .all(|(found, expected)| operand_matches(*found, *expected))
3474 && (state.reachability == Reachability::Unreachable || actual.len() == expected.len())
3475 {
3476 Ok(())
3477 } else {
3478 Err(found)
3479 }
3480}
3481
3482fn pop_operand(
3483 function: FuncIdx,
3484 state: &mut ValidationState,
3485 offset: usize,
3486 op: &'static str,
3487 expected: &[ValType],
3488) -> Result<OperandType, ValidationError> {
3489 if is_stack_polymorphic(state) {
3490 return Ok(OperandType::Bottom);
3491 }
3492
3493 match state.operands.pop() {
3494 Some(found) => Ok(found),
3495 None => Err(underflow_error(function, state, op, expected, offset)),
3496 }
3497}
3498
3499fn underflow_error(
3500 function: FuncIdx,
3501 state: &ValidationState,
3502 op: &'static str,
3503 expected: &[ValType],
3504 offset: usize,
3505) -> ValidationError {
3506 ValidationError {
3507 offset: ByteOffset(offset),
3508 function: Some(function),
3509 kind: ValidationErrorKind::StackUnderflow {
3510 op,
3511 expected: expected.to_vec(),
3512 available: concrete_stack(state),
3513 },
3514 }
3515}
3516
3517fn pop_expect(
3518 function: FuncIdx,
3519 state: &mut ValidationState,
3520 expected: ValType,
3521 offset: usize,
3522 op: &'static str,
3523) -> Result<(), ValidationError> {
3524 let found = pop_operand(function, state, offset, op, &[expected])?;
3525 if !operand_matches(found, expected) {
3526 return Err(ValidationError {
3527 offset: ByteOffset(offset),
3528 function: Some(function),
3529 kind: ValidationErrorKind::TypeMismatch {
3530 op,
3531 expected,
3532 found: operand_to_valtype(found, expected),
3533 },
3534 });
3535 }
3536 Ok(())
3537}
3538
3539fn pop_exact(
3540 function: FuncIdx,
3541 state: &mut ValidationState,
3542 expected: &[ValType],
3543 offset: usize,
3544) -> Result<(), ValidationError> {
3545 for expected_ty in expected.iter().rev() {
3546 pop_expect(function, state, *expected_ty, offset, "stack")?;
3547 }
3548 Ok(())
3549}
3550
3551fn validate_tail_call_results(
3552 function: FuncIdx,
3553 state: &ValidationState,
3554 found: &[ValType],
3555 offset: usize,
3556) -> Result<(), ValidationError> {
3557 let expected = &state.controls[0].end_types;
3558 if !valtype_vec_matches(found, expected) {
3559 return Err(ValidationError {
3560 offset: ByteOffset(offset),
3561 function: Some(function),
3562 kind: ValidationErrorKind::ResultTypeMismatch {
3563 expected: expected.clone(),
3564 found: found.to_vec(),
3565 },
3566 });
3567 }
3568
3569 Ok(())
3570}
3571
3572fn pop_branch_types(
3573 function: FuncIdx,
3574 state: &mut ValidationState,
3575 label: crate::types::LabelIdx,
3576 expected: &[ValType],
3577 offset: usize,
3578) -> Result<(), ValidationError> {
3579 ensure_stack_types(state, expected).map_err(|found| ValidationError {
3580 offset: ByteOffset(offset),
3581 function: Some(function),
3582 kind: ValidationErrorKind::BranchTypeMismatch {
3583 label,
3584 expected: expected.to_vec(),
3585 found,
3586 },
3587 })?;
3588 pop_exact(function, state, expected, offset)
3589}
3590
3591fn pop_control_result_types(
3592 function: FuncIdx,
3593 state: &mut ValidationState,
3594 expected: &[ValType],
3595 offset: usize,
3596) -> Result<(), ValidationError> {
3597 ensure_stack_types(state, expected).map_err(|found| ValidationError {
3598 offset: ByteOffset(offset),
3599 function: Some(function),
3600 kind: ValidationErrorKind::ControlResultTypeMismatch {
3601 expected: expected.to_vec(),
3602 found,
3603 },
3604 })?;
3605 pop_exact(function, state, expected, offset)
3606}
3607
3608fn ensure_stack_types(state: &ValidationState, expected: &[ValType]) -> Result<(), Vec<ValType>> {
3609 if is_stack_polymorphic(state) {
3610 return Ok(());
3611 }
3612
3613 let operands = state.operands.as_slice();
3614 let found_len = core::cmp::min(operands.len(), expected.len());
3615 let found = &operands[operands.len().saturating_sub(found_len)..];
3616 let expected_suffix = &expected[expected.len() - found_len..];
3617
3618 if (state.reachability == Reachability::Reachable && operands.len() < expected.len())
3619 || !found
3620 .iter()
3621 .zip(expected_suffix)
3622 .all(|(found, expected)| operand_matches(*found, *expected))
3623 {
3624 return Err(found
3625 .iter()
3626 .zip(expected_suffix)
3627 .map(|(found, expected)| operand_to_valtype(*found, *expected))
3628 .collect());
3629 }
3630
3631 Ok(())
3632}
3633
3634fn pop_operand_type(
3635 function: FuncIdx,
3636 state: &mut ValidationState,
3637 offset: usize,
3638 op: &'static str,
3639) -> Result<OperandType, ValidationError> {
3640 pop_operand(function, state, offset, op, &[])
3641}
3642
3643fn pop_ref_type(
3644 function: FuncIdx,
3645 state: &mut ValidationState,
3646 offset: usize,
3647 op: &'static str,
3648) -> Result<Option<RefType>, ValidationError> {
3649 let found = pop_operand_type(function, state, offset, op)?;
3650 match found {
3651 OperandType::Bottom => Ok(None),
3652 OperandType::Typed(ValType::Ref(ref_type)) => Ok(Some(ref_type)),
3653 OperandType::Typed(found) => Err(ValidationError {
3654 offset: ByteOffset(offset),
3655 function: Some(function),
3656 kind: ValidationErrorKind::TypeMismatch {
3657 op,
3658 expected: ValType::Ref(RefType::ExternRef),
3659 found,
3660 },
3661 }),
3662 }
3663}
3664
3665fn pop_any(
3666 function: FuncIdx,
3667 state: &mut ValidationState,
3668 offset: usize,
3669 op: &'static str,
3670) -> Result<(), ValidationError> {
3671 pop_operand(function, state, offset, op, &[]).map(|_| ())
3672}
3673
3674fn expand_locals(
3675 module: &Module<'_>,
3676 function: FuncIdx,
3677 locals: &mut Vec<ValType>,
3678 local_decls: &[LocalDecl],
3679 offset: usize,
3680) -> Result<(), ValidationError> {
3681 for decl in local_decls {
3682 validate_valtype_type_indices(module, decl.val_type, Some(function), offset)?;
3683 for _ in 0..decl.count {
3684 locals.push(normalize_valtype(module, decl.val_type));
3685 }
3686 }
3687 Ok(())
3688}
3689
3690#[cfg(test)]
3691mod tests {
3692 use super::*;
3693 use crate::binary::module::Module;
3694 use crate::types::{LabelIdx, LocalIdx};
3695
3696 #[test]
3697 fn validate_simple_add_module() {
3698 let bytes = [
3699 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7F,
3700 0x7F, 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00,
3701 0x20, 0x01, 0x6A, 0x0B,
3702 ];
3703 let module = Module::decode(&bytes).unwrap();
3704 module.validate().unwrap();
3705 }
3706
3707 #[test]
3708 fn reject_unknown_local_index() {
3709 let bytes = [
3710 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
3711 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x06, 0x01, 0x04, 0x00, 0x20, 0x00, 0x0B,
3712 ];
3713 let module = Module::decode(&bytes).unwrap();
3714 let err = module.validate().unwrap_err();
3715 assert!(matches!(
3716 err.kind,
3717 ValidationErrorKind::UnknownLocalIdx { .. }
3718 ));
3719 assert_eq!(err.offset, ByteOffset(24));
3720 }
3721
3722 #[test]
3723 fn validate_forward_mutual_recursion() {
3724 let bytes =
3725 include_bytes!("../../../baedeker-testdata/spec/valid/forward-mutual-recursion.wasm");
3726 let module = Module::decode(bytes).unwrap();
3727 module.validate().unwrap();
3728 }
3729
3730 #[test]
3731 fn validate_local_get_after_set_for_non_defaultable_local() {
3732 let bytes =
3733 include_bytes!("../../../baedeker-testdata/spec/valid/local-init-get-after-set.wasm");
3734 let module = Module::decode(bytes).unwrap();
3735 module.validate().unwrap();
3736 }
3737
3738 #[test]
3739 fn validate_local_get_after_tee_for_non_defaultable_local() {
3740 let bytes =
3741 include_bytes!("../../../baedeker-testdata/spec/valid/local-init-get-after-tee.wasm");
3742 let module = Module::decode(bytes).unwrap();
3743 module.validate().unwrap();
3744 }
3745
3746 #[test]
3747 fn validate_local_get_in_block_after_set_for_non_defaultable_local() {
3748 let bytes = include_bytes!(
3749 "../../../baedeker-testdata/spec/valid/local-init-get-in-block-after-set.wasm",
3750 );
3751 let module = Module::decode(bytes).unwrap();
3752 module.validate().unwrap();
3753 }
3754
3755 #[test]
3756 fn validate_local_tee_init_official_case() {
3757 let bytes =
3758 include_bytes!("../../../baedeker-testdata/spec/valid/local-init-tee-init.wasm");
3759 let module = Module::decode(bytes).unwrap();
3760 module.validate().unwrap();
3761 }
3762
3763 #[test]
3764 fn reject_uninitialized_non_defaultable_local() {
3765 let bytes = include_bytes!(
3766 "../../../baedeker-testdata/spec/invalid-validate/local-init-uninitialized-local.wasm",
3767 );
3768 let module = Module::decode(bytes).unwrap();
3769 let err = module.validate().unwrap_err();
3770 assert_eq!(err.offset, ByteOffset(26));
3771 assert!(matches!(
3772 err.kind,
3773 ValidationErrorKind::UninitializedLocal { idx: LocalIdx(0) }
3774 ));
3775 }
3776
3777 #[test]
3778 fn reject_non_defaultable_local_initialized_only_inside_block() {
3779 let bytes = include_bytes!(
3780 "../../../baedeker-testdata/spec/invalid-validate/local-init-uninitialized-after-end.wasm",
3781 );
3782 let module = Module::decode(bytes).unwrap();
3783 let err = module.validate().unwrap_err();
3784 assert_eq!(err.offset, ByteOffset(40));
3785 assert!(matches!(
3786 err.kind,
3787 ValidationErrorKind::UninitializedLocal { idx: LocalIdx(1) }
3788 ));
3789 }
3790
3791 #[test]
3792 fn reject_non_defaultable_local_get_in_else_without_prior_init() {
3793 let bytes = include_bytes!(
3794 "../../../baedeker-testdata/spec/invalid-validate/local-init-uninitialized-in-else.wasm",
3795 );
3796 let module = Module::decode(bytes).unwrap();
3797 let err = module.validate().unwrap_err();
3798 assert_eq!(err.offset, ByteOffset(37));
3799 assert!(matches!(
3800 err.kind,
3801 ValidationErrorKind::UninitializedLocal { idx: LocalIdx(1) }
3802 ));
3803 }
3804
3805 #[test]
3806 fn reject_non_defaultable_local_init_not_escaping_if() {
3807 let bytes = include_bytes!(
3808 "../../../baedeker-testdata/spec/invalid-validate/local-init-uninitialized-from-if.wasm",
3809 );
3810 let module = Module::decode(bytes).unwrap();
3811 let err = module.validate().unwrap_err();
3812 assert_eq!(err.offset, ByteOffset(42));
3813 assert!(matches!(
3814 err.kind,
3815 ValidationErrorKind::UninitializedLocal { idx: LocalIdx(1) }
3816 ));
3817 }
3818
3819 #[test]
3820 fn validate_unreached_call_ref() {
3821 let bytes = include_bytes!("../../../baedeker-testdata/spec/valid/unreached-call-ref.wasm");
3822 let module = Module::decode(bytes).unwrap();
3823 module.validate().unwrap();
3824 }
3825
3826 #[test]
3827 fn validate_select_after_unreachable_with_bottom_operands() {
3828 let bytes = include_bytes!(
3829 "../../../baedeker-testdata/spec/valid/unreached-valid-select-after-unreachable.wasm",
3830 );
3831 let module = Module::decode(bytes).unwrap();
3832 module.validate().unwrap();
3833 }
3834
3835 #[test]
3836 fn validate_unreached_core_stack_polymorphism_cases() {
3837 let bytes =
3838 include_bytes!("../../../baedeker-testdata/spec/valid/unreached-valid-core.wasm");
3839 let module = Module::decode(bytes).unwrap();
3840 module.validate().unwrap();
3841 }
3842
3843 #[test]
3844 fn validate_unreached_bottom_heap_type_cases() {
3845 let bytes =
3846 include_bytes!("../../../baedeker-testdata/spec/valid/unreached-bottom-heap-type.wasm");
3847 let module = Module::decode(bytes).unwrap();
3848 module.validate().unwrap();
3849 }
3850
3851 #[test]
3852 fn validate_unreached_meet_bottom_br_table() {
3853 let bytes =
3854 include_bytes!("../../../baedeker-testdata/spec/valid/unreached-meet-bottom.wasm");
3855 let module = Module::decode(bytes).unwrap();
3856 module.validate().unwrap();
3857 }
3858
3859 #[test]
3860 fn validate_unreached_select_i64_result_official_case() {
3861 let bytes = include_bytes!(
3862 "../../../baedeker-testdata/spec/valid/unreached-valid-select-i64-result.wasm",
3863 );
3864 let module = Module::decode(bytes).unwrap();
3865 module.validate().unwrap();
3866 }
3867
3868 #[test]
3869 fn reject_unreached_select_result_mismatch() {
3870 let bytes = include_bytes!(
3871 "../../../baedeker-testdata/spec/invalid-validate/unreached-select-result-mismatch.wasm",
3872 );
3873 let module = Module::decode(bytes).unwrap();
3874 let err = module.validate().unwrap_err();
3875 assert_eq!(err.offset, ByteOffset(30));
3876 assert!(matches!(
3877 err.kind,
3878 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
3879 if expected == vec![ValType::Num(crate::types::NumType::I32)]
3880 && found == vec![ValType::Num(crate::types::NumType::I64)]
3881 ));
3882 }
3883
3884 #[test]
3885 fn reject_unreached_unconsumed_const() {
3886 let bytes = include_bytes!(
3887 "../../../baedeker-testdata/spec/invalid-validate/unreached-unconsumed-const.wasm",
3888 );
3889 let module = Module::decode(bytes).unwrap();
3890 let err = module.validate().unwrap_err();
3891 assert_eq!(err.offset, ByteOffset(26));
3892 assert!(matches!(
3893 err.kind,
3894 ValidationErrorKind::FunctionResultTypeMismatch { expected, .. }
3895 if expected.is_empty()
3896 ));
3897 }
3898
3899 #[test]
3900 fn reject_unknown_local_index_in_unreachable_code() {
3901 let bytes = include_bytes!(
3902 "../../../baedeker-testdata/spec/invalid-validate/unreached-unknown-local-index.wasm",
3903 );
3904 let module = Module::decode(bytes).unwrap();
3905 let err = module.validate().unwrap_err();
3906 assert_eq!(err.offset, ByteOffset(24));
3907 assert!(matches!(
3908 err.kind,
3909 ValidationErrorKind::UnknownLocalIdx { idx: LocalIdx(0) }
3910 ));
3911 }
3912
3913 #[test]
3914 fn reject_unknown_global_index_in_unreachable_code() {
3915 let bytes = include_bytes!(
3916 "../../../baedeker-testdata/spec/invalid-validate/unreached-unknown-global-index.wasm",
3917 );
3918 let module = Module::decode(bytes).unwrap();
3919 let err = module.validate().unwrap_err();
3920 assert_eq!(err.offset, ByteOffset(24));
3921 assert!(matches!(
3922 err.kind,
3923 ValidationErrorKind::UnknownGlobalIdx {
3924 idx: GlobalIdx(0),
3925 available: 0,
3926 }
3927 ));
3928 }
3929
3930 #[test]
3931 fn reject_unknown_function_index_in_unreachable_code() {
3932 let bytes = include_bytes!(
3933 "../../../baedeker-testdata/spec/invalid-validate/unreached-unknown-function-index.wasm",
3934 );
3935 let module = Module::decode(bytes).unwrap();
3936 let err = module.validate().unwrap_err();
3937 assert_eq!(err.offset, ByteOffset(24));
3938 assert!(matches!(
3939 err.kind,
3940 ValidationErrorKind::UnknownFuncIdx { idx: FuncIdx(1) }
3941 ));
3942 }
3943
3944 #[test]
3945 fn reject_unknown_label_index_in_unreachable_code() {
3946 let bytes = include_bytes!(
3947 "../../../baedeker-testdata/spec/invalid-validate/unreached-unknown-label-index.wasm",
3948 );
3949 let module = Module::decode(bytes).unwrap();
3950 let err = module.validate().unwrap_err();
3951 assert_eq!(err.offset, ByteOffset(24));
3952 assert!(matches!(
3953 err.kind,
3954 ValidationErrorKind::UnknownLabelIdx { idx: LabelIdx(1) }
3955 ));
3956 }
3957
3958 #[test]
3959 fn validate_unreachable_function_end_with_result_type() {
3960 let bytes = [
3961 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
3962 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x05, 0x01, 0x03, 0x00, 0x00, 0x0B,
3963 ];
3964 let module = Module::decode(&bytes).unwrap();
3965 module.validate().unwrap();
3966 }
3967
3968 #[test]
3969 fn report_stack_underflow_with_operation_context() {
3970 let bytes = [
3971 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
3972 0x03, 0x02, 0x01, 0x00, 0x0A, 0x05, 0x01, 0x03, 0x00, 0x6A, 0x0B,
3973 ];
3974 let module = Module::decode(&bytes).unwrap();
3975 let err = module.validate().unwrap_err();
3976 assert_eq!(err.offset, ByteOffset(23));
3977 assert!(matches!(
3978 err.kind,
3979 ValidationErrorKind::StackUnderflow { op, expected, available }
3980 if op == "i32.binary"
3981 && expected == vec![ValType::Num(crate::types::NumType::I32)]
3982 && available.is_empty()
3983 ));
3984 }
3985
3986 #[test]
3987 fn report_type_mismatch_with_operation_context() {
3988 let bytes = [
3989 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
3990 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x42, 0x01, 0x41, 0x02, 0x6A,
3991 0x0B,
3992 ];
3993 let module = Module::decode(&bytes).unwrap();
3994 let err = module.validate().unwrap_err();
3995 assert_eq!(err.offset, ByteOffset(27));
3996 assert!(matches!(
3997 err.kind,
3998 ValidationErrorKind::TypeMismatch { op, expected, found }
3999 if op == "i32.binary"
4000 && expected == ValType::Num(crate::types::NumType::I32)
4001 && found == ValType::Num(crate::types::NumType::I64)
4002 ));
4003 }
4004
4005 #[test]
4006 fn report_precise_offset_for_later_instruction() {
4007 let bytes = [
4008 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F,
4009 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20,
4010 0x01, 0x6A, 0x0B,
4011 ];
4012 let module = Module::decode(&bytes).unwrap();
4013 let err = module.validate().unwrap_err();
4014 assert!(matches!(
4015 err.kind,
4016 ValidationErrorKind::UnknownLocalIdx { .. }
4017 ));
4018 assert_eq!(err.offset, ByteOffset(27));
4019 }
4020
4021 #[test]
4022 fn reject_unknown_function_type_index() {
4023 let bytes = [
4024 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x02, 0x01,
4025 0x01, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
4026 ];
4027 let module = Module::decode(&bytes).unwrap();
4028 let err = module.validate().unwrap_err();
4029 assert!(matches!(
4030 err.kind,
4031 ValidationErrorKind::UnknownTypeIdx { .. }
4032 ));
4033 }
4034
4035 #[test]
4036 fn reject_import_with_unknown_type_index() {
4037 let bytes = [
4038 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
4039 0x7F, 0x02, 0x0D, 0x01, 0x04, b't', b'e', b's', b't', 0x04, b'f', b'u', b'n', b'c',
4040 0x00, 0x01,
4041 ];
4042 let module = Module::decode(&bytes).unwrap();
4043 let err = module.validate().unwrap_err();
4044 assert!(matches!(
4045 err.kind,
4046 ValidationErrorKind::UnknownTypeIdx {
4047 idx: crate::types::TypeIdx(1)
4048 }
4049 ));
4050 }
4051
4052 #[test]
4053 fn reject_typed_function_type_with_unknown_concrete_type_idx() {
4054 let bytes = [
4055 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x63,
4056 0x01, 0x00, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0x20, 0x00, 0x1A,
4057 0x0B,
4058 ];
4059 let module = Module::decode(&bytes).unwrap();
4060 let err = module.validate().unwrap_err();
4061 assert_eq!(err.offset, ByteOffset(10));
4062 assert!(matches!(
4063 err.kind,
4064 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4065 ));
4066 }
4067
4068 #[test]
4069 fn reject_imported_typed_global_with_unknown_concrete_type_idx() {
4070 let bytes = [
4071 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4072 0x02, 0x0B, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x63, 0x01, 0x00,
4073 ];
4074 let module = Module::decode(&bytes).unwrap();
4075 let err = module.validate().unwrap_err();
4076 assert_eq!(err.offset, ByteOffset(16));
4077 assert!(matches!(
4078 err.kind,
4079 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4080 ));
4081 }
4082
4083 #[test]
4084 fn reject_typed_table_with_unknown_concrete_type_idx() {
4085 let bytes = [
4086 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4087 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x01,
4088 ];
4089 let module = Module::decode(&bytes).unwrap();
4090 let err = module.validate().unwrap_err();
4091 assert_eq!(err.offset, ByteOffset(16));
4092 assert!(matches!(
4093 err.kind,
4094 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4095 ));
4096 }
4097
4098 #[test]
4099 fn reject_typed_element_with_unknown_concrete_type_idx() {
4100 let bytes = [
4101 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4102 0x09, 0x08, 0x01, 0x05, 0x63, 0x01, 0x01, 0xD0, 0x01, 0x0B,
4103 ];
4104 let module = Module::decode(&bytes).unwrap();
4105 let err = module.validate().unwrap_err();
4106 assert_eq!(err.offset, ByteOffset(16));
4107 assert!(matches!(
4108 err.kind,
4109 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4110 ));
4111 }
4112
4113 #[test]
4114 fn reject_typed_local_with_unknown_concrete_type_idx() {
4115 let bytes = [
4116 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4117 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x01, 0x01, 0x63, 0x01, 0x0B,
4118 ];
4119 let module = Module::decode(&bytes).unwrap();
4120 let err = module.validate().unwrap_err();
4121 assert_eq!(err.offset, ByteOffset(26));
4122 assert!(matches!(
4123 err.kind,
4124 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4125 ));
4126 }
4127
4128 #[test]
4129 fn reject_ref_null_with_unknown_concrete_type_idx() {
4130 let bytes = [
4131 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4132 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xD0, 0x01, 0x1A, 0x0B,
4133 ];
4134 let module = Module::decode(&bytes).unwrap();
4135 let err = module.validate().unwrap_err();
4136 assert_eq!(err.offset, ByteOffset(23));
4137 assert!(matches!(
4138 err.kind,
4139 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4140 ));
4141 }
4142
4143 #[test]
4144 fn reject_block_result_with_unknown_concrete_type_idx() {
4145 let bytes = [
4146 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4147 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0B, 0x01, 0x09, 0x00, 0x02, 0x63, 0x01, 0xD0, 0x01,
4148 0x1A, 0x0B, 0x0B,
4149 ];
4150 let module = Module::decode(&bytes).unwrap();
4151 let err = module.validate().unwrap_err();
4152 assert_eq!(err.offset, ByteOffset(23));
4153 assert!(matches!(
4154 err.kind,
4155 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4156 ));
4157 }
4158
4159 #[test]
4160 fn reject_forward_type_reference_outside_rec_group() {
4161 let bytes = include_bytes!(
4162 "../../../baedeker-testdata/spec/invalid-validate/type-forward-ref-outside-rec-group.wasm",
4163 );
4164 let module = Module::decode(bytes).unwrap();
4165 let err = module.validate().unwrap_err();
4166 assert_eq!(err.offset, ByteOffset(10));
4167 assert!(matches!(
4168 err.kind,
4169 ValidationErrorKind::UnknownTypeIdx { idx: TypeIdx(1) }
4170 ));
4171 }
4172
4173 #[test]
4174 fn report_function_result_stack_suffix() {
4175 let bytes = [
4176 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
4177 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0x41, 0x01, 0x41, 0x02,
4178 0x0B,
4179 ];
4180 let module = Module::decode(&bytes).unwrap();
4181 let err = module.validate().unwrap_err();
4182 assert_eq!(err.offset, ByteOffset(28));
4183 assert!(matches!(
4184 err.kind,
4185 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, full_stack }
4186 if expected == vec![ValType::Num(crate::types::NumType::I32)]
4187 && found == vec![ValType::Num(crate::types::NumType::I32)]
4188 && full_stack == vec![
4189 ValType::Num(crate::types::NumType::I32),
4190 ValType::Num(crate::types::NumType::I32),
4191 ]
4192 ));
4193 }
4194
4195 #[test]
4196 fn validate_unreachable_stack_polymorphism_after_br() {
4197 let bytes = [
4198 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4199 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x01, 0x08, 0x00, 0x02, 0x40, 0x0C, 0x00, 0x1A,
4200 0x0B, 0x0B,
4201 ];
4202 let module = Module::decode(&bytes).unwrap();
4203 module.validate().unwrap();
4204 }
4205
4206 #[test]
4207 fn validate_typed_unreachable_block_dead_ref_with_equivalent_signature() {
4208 let bytes = [
4209 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
4210 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
4211 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x10, 0x02, 0x04,
4212 0x00, 0x20, 0x00, 0x0b, 0x09, 0x00, 0x02, 0x63, 0x01, 0x00, 0xd2, 0x00, 0x0b, 0x0b,
4213 ];
4214 let module = Module::decode(&bytes).unwrap();
4215 module.validate().unwrap();
4216 }
4217
4218 #[test]
4219 fn reject_typed_unreachable_block_dead_ref_with_wrong_concrete_type() {
4220 let bytes = [
4221 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7e,
4222 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
4223 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x10, 0x02, 0x04,
4224 0x00, 0x20, 0x00, 0x0b, 0x09, 0x00, 0x02, 0x63, 0x01, 0x00, 0xd2, 0x00, 0x0b, 0x0b,
4225 ];
4226 let module = Module::decode(&bytes).unwrap();
4227 let err = module.validate().unwrap_err();
4228 assert_eq!(err.offset, ByteOffset(54));
4229 assert!(matches!(
4230 err.kind,
4231 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
4232 if expected == vec![ValType::Ref(RefType::Typed {
4233 nullable: true,
4234 heap: crate::types::HeapType::Type(TypeIdx(1)),
4235 })] && found == vec![ValType::Ref(RefType::Typed {
4236 nullable: false,
4237 heap: crate::types::HeapType::Type(TypeIdx(0)),
4238 })]
4239 ));
4240 }
4241
4242 #[test]
4243 fn validate_typed_br_dead_ref_with_equivalent_signature() {
4244 let bytes = [
4245 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
4246 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03,
4247 0x02, 0x01, 0x02, 0x07, 0x06, 0x01, 0x02, 0x66, 0x31, 0x00, 0x00, 0x0a, 0x13, 0x02,
4248 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x02, 0x63, 0x00, 0xd2, 0x00, 0x0c, 0x00,
4249 0xd0, 0x01, 0x0b, 0x0b,
4250 ];
4251 let module = Module::decode(&bytes).unwrap();
4252 module.validate().unwrap();
4253 }
4254
4255 #[test]
4256 fn reject_typed_br_dead_ref_with_wrong_concrete_type() {
4257 let bytes = include_bytes!(
4258 "../../../baedeker-testdata/spec/invalid-validate/typed-br-dead-ref-wrong-concrete-type.wasm",
4259 );
4260 let module = Module::decode(bytes).unwrap();
4261 let err = module.validate().unwrap_err();
4262 assert_eq!(err.offset, ByteOffset(58));
4263 assert!(matches!(
4264 err.kind,
4265 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
4266 if expected == vec![ValType::Ref(RefType::Typed {
4267 nullable: true,
4268 heap: crate::types::HeapType::Type(TypeIdx(1)),
4269 })] && found == vec![ValType::Ref(RefType::Typed {
4270 nullable: true,
4271 heap: crate::types::HeapType::Type(TypeIdx(0)),
4272 })]
4273 ));
4274 }
4275
4276 #[test]
4277 fn validate_typed_select_to_br_nullable_official_case() {
4278 let bytes = include_bytes!(
4279 "../../../baedeker-testdata/spec/valid/typed-select-to-br-nullable.wasm",
4280 );
4281 let module = Module::decode(bytes).unwrap();
4282 module.validate().unwrap();
4283 }
4284
4285 #[test]
4286 fn reject_typed_select_to_br_nullability_mismatch() {
4287 let bytes = include_bytes!(
4288 "../../../baedeker-testdata/spec/invalid-validate/typed-select-to-br-nullability-mismatch.wasm",
4289 );
4290 let module = Module::decode(bytes).unwrap();
4291 let err = module.validate().unwrap_err();
4292 assert_eq!(err.offset, ByteOffset(57));
4293 assert!(matches!(
4294 err.kind,
4295 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
4296 if label == crate::types::LabelIdx(0)
4297 && expected == vec![ValType::Ref(RefType::Typed {
4298 nullable: false,
4299 heap: crate::types::HeapType::Type(TypeIdx(0)),
4300 })]
4301 && found == vec![ValType::Ref(RefType::Typed {
4302 nullable: true,
4303 heap: crate::types::HeapType::Type(TypeIdx(0)),
4304 })]
4305 ));
4306 }
4307
4308 #[test]
4309 fn validate_typed_table_init_to_br_nullable_official_case() {
4310 let bytes = include_bytes!(
4311 "../../../baedeker-testdata/spec/valid/typed-table-init-to-br-nullable.wasm",
4312 );
4313 let module = Module::decode(bytes).unwrap();
4314 module.validate().unwrap();
4315 }
4316
4317 #[test]
4318 fn reject_typed_table_init_to_br_nullability_mismatch() {
4319 let bytes = include_bytes!(
4320 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-to-br-nullability-mismatch.wasm",
4321 );
4322 let module = Module::decode(bytes).unwrap();
4323 let err = module.validate().unwrap_err();
4324 assert_eq!(err.offset, ByteOffset(86));
4325 assert!(matches!(
4326 err.kind,
4327 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
4328 if label == crate::types::LabelIdx(0)
4329 && expected == vec![ValType::Ref(RefType::Typed {
4330 nullable: false,
4331 heap: crate::types::HeapType::Type(TypeIdx(0)),
4332 })]
4333 && found == vec![ValType::Ref(RefType::Typed {
4334 nullable: true,
4335 heap: crate::types::HeapType::Type(TypeIdx(0)),
4336 })]
4337 ));
4338 }
4339
4340 #[test]
4341 fn validate_typed_table_init_shared_source_to_br_nullable_official_case() {
4342 let bytes = include_bytes!(
4343 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-br-nullable.wasm",
4344 );
4345 let module = Module::decode(bytes).unwrap();
4346 module.validate().unwrap();
4347 }
4348
4349 #[test]
4350 fn reject_typed_table_init_shared_source_to_br_nullability_mismatch() {
4351 let bytes = include_bytes!(
4352 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-br-nullability-mismatch.wasm",
4353 );
4354 let module = Module::decode(bytes).unwrap();
4355 let err = module.validate().unwrap_err();
4356 assert_eq!(err.offset, ByteOffset(97));
4357 assert!(matches!(
4358 err.kind,
4359 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
4360 if label == crate::types::LabelIdx(0)
4361 && expected == vec![ValType::Ref(RefType::Typed {
4362 nullable: false,
4363 heap: crate::types::HeapType::Type(TypeIdx(1)),
4364 })]
4365 && found == vec![ValType::Ref(RefType::Typed {
4366 nullable: true,
4367 heap: crate::types::HeapType::Type(TypeIdx(1)),
4368 })]
4369 ));
4370 }
4371
4372 #[test]
4373 fn validate_imported_global_get_and_set() {
4374 let bytes = [
4375 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4376 0x02, 0x0A, 0x01, 0x03, b'e', b'n', b'v', 0x01, b'g', 0x03, 0x7F, 0x01, 0x03, 0x02,
4377 0x01, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0x23, 0x00, 0x24, 0x00, 0x0B,
4378 ];
4379 let module = Module::decode(&bytes).unwrap();
4380 module.validate().unwrap();
4381 }
4382
4383 #[test]
4384 fn reject_global_set_on_immutable_global() {
4385 let bytes = [
4386 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4387 0x03, 0x02, 0x01, 0x00, 0x06, 0x09, 0x01, 0x7D, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00,
4388 0x0B, 0x0A, 0x0B, 0x01, 0x09, 0x00, 0x43, 0x00, 0x00, 0x80, 0x3F, 0x24, 0x00, 0x0B,
4389 ];
4390 let module = Module::decode(&bytes).unwrap();
4391 let err = module.validate().unwrap_err();
4392 assert!(matches!(
4393 err.kind,
4394 ValidationErrorKind::ImmutableGlobalSet { idx: GlobalIdx(0) }
4395 ));
4396 assert_eq!(err.offset.0, 39);
4397 }
4398
4399 #[test]
4400 fn validate_defined_global_get() {
4401 let bytes = [
4402 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
4403 0x7F, 0x03, 0x02, 0x01, 0x00, 0x06, 0x06, 0x01, 0x7F, 0x00, 0x41, 0x2A, 0x0B, 0x0A,
4404 0x06, 0x01, 0x04, 0x00, 0x23, 0x00, 0x0B,
4405 ];
4406 let module = Module::decode(&bytes).unwrap();
4407 module.validate().unwrap();
4408 }
4409
4410 #[test]
4411 fn validate_ref_is_null() {
4412 let bytes = [
4413 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
4414 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xD0, 0x6F, 0xD1, 0x0B,
4415 ];
4416 let module = Module::decode(&bytes).unwrap();
4417 module.validate().unwrap();
4418 }
4419
4420 #[test]
4421 fn reject_ref_is_null_on_non_ref() {
4422 let bytes = [
4423 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
4424 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0x41, 0x00, 0xD1, 0x0B,
4425 ];
4426 let module = Module::decode(&bytes).unwrap();
4427 let err = module.validate().unwrap_err();
4428 assert_eq!(err.offset, ByteOffset(26));
4429 assert!(matches!(
4430 err.kind,
4431 ValidationErrorKind::TypeMismatch {
4432 op: "ref.is_null",
4433 found: ValType::Num(crate::types::NumType::I32),
4434 ..
4435 }
4436 ));
4437 }
4438
4439 #[test]
4440 fn validate_ref_as_non_null() {
4441 let bytes = [
4442 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x00, 0x01,
4443 0x7F, 0x60, 0x01, 0x63, 0x00, 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x01, 0x07, 0x05,
4444 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x0E, 0x02, 0x04, 0x00, 0x41, 0x07, 0x0B, 0x07,
4445 0x00, 0x20, 0x00, 0xD4, 0x14, 0x00, 0x0B,
4446 ];
4447 let module = Module::decode(&bytes).unwrap();
4448 module.validate().unwrap();
4449 }
4450
4451 #[test]
4452 fn validate_ref_as_non_null_after_unreachable_official_case() {
4453 let bytes = include_bytes!(
4454 "../../../baedeker-testdata/spec/valid/ref-as-non-null-unreachable.wasm"
4455 );
4456 let module = Module::decode(bytes).unwrap();
4457 module.validate().unwrap();
4458 }
4459
4460 #[test]
4461 fn validate_ref_as_non_null_direct_call_ref_func_official_case() {
4462 let bytes = include_bytes!(
4463 "../../../baedeker-testdata/spec/valid/ref-as-non-null-direct-call-ref-func.wasm",
4464 );
4465 let module = Module::decode(bytes).unwrap();
4466 module.validate().unwrap();
4467 }
4468
4469 #[test]
4470 fn reject_ref_as_non_null_on_non_ref() {
4471 let bytes = [
4472 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4473 0x03, 0x02, 0x01, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0x41, 0x00, 0xD4, 0x1A, 0x0B,
4474 ];
4475 let module = Module::decode(&bytes).unwrap();
4476 let err = module.validate().unwrap_err();
4477 assert_eq!(err.offset, ByteOffset(25));
4478 assert!(matches!(
4479 err.kind,
4480 ValidationErrorKind::TypeMismatch {
4481 op: "ref.as_non_null",
4482 expected: ValType::Ref(RefType::ExternRef),
4483 found: ValType::Num(crate::types::NumType::I32),
4484 }
4485 ));
4486 }
4487
4488 #[test]
4489 fn reject_ref_as_non_null_null_to_nonnull_call_official_case() {
4490 let bytes = include_bytes!(
4491 "../../../baedeker-testdata/spec/invalid-validate/ref-as-non-null-null-to-nonnull-call.wasm",
4492 );
4493 let module = Module::decode(bytes).unwrap();
4494 let err = module.validate().unwrap_err();
4495 assert_eq!(err.offset, ByteOffset(42));
4496 assert!(matches!(
4497 err.kind,
4498 ValidationErrorKind::TypeMismatch { op, expected, found }
4499 if op == "stack"
4500 && expected == ValType::Ref(RefType::Typed {
4501 nullable: false,
4502 heap: crate::types::HeapType::Type(TypeIdx(0)),
4503 })
4504 && found == ValType::Ref(RefType::Typed {
4505 nullable: true,
4506 heap: crate::types::HeapType::Type(TypeIdx(0)),
4507 })
4508 ));
4509 }
4510
4511 #[test]
4512 fn validate_typed_ref_as_non_null_global_set_with_equivalent_signature() {
4513 let bytes = include_bytes!(
4514 "../../../baedeker-testdata/spec/valid/typed-ref-as-non-null-global-set-equivalent-signature.wasm",
4515 );
4516 let module = Module::decode(bytes).unwrap();
4517 module.validate().unwrap();
4518 }
4519
4520 #[test]
4521 fn reject_typed_ref_as_non_null_global_set_with_wrong_concrete_type() {
4522 let bytes = include_bytes!(
4523 "../../../baedeker-testdata/spec/invalid-validate/typed-ref-as-non-null-global-set-wrong-concrete-type.wasm",
4524 );
4525 let module = Module::decode(bytes).unwrap();
4526 let err = module.validate().unwrap_err();
4527 assert_eq!(err.offset, ByteOffset(51));
4528 assert!(matches!(
4529 err.kind,
4530 ValidationErrorKind::TypeMismatch { op, expected, found }
4531 if op == "global.set"
4532 && expected == ValType::Ref(RefType::Typed {
4533 nullable: true,
4534 heap: crate::types::HeapType::Type(TypeIdx(1)),
4535 })
4536 && found == ValType::Ref(RefType::Typed {
4537 nullable: false,
4538 heap: crate::types::HeapType::Type(TypeIdx(0)),
4539 })
4540 ));
4541 }
4542
4543 #[test]
4544 fn validate_typed_ref_as_non_null_if_join_with_equivalent_signature() {
4545 let bytes = include_bytes!(
4546 "../../../baedeker-testdata/spec/valid/typed-ref-as-non-null-if-join-equivalent-signature.wasm",
4547 );
4548 let module = Module::decode(bytes).unwrap();
4549 module.validate().unwrap();
4550 }
4551
4552 #[test]
4553 fn reject_typed_ref_as_non_null_if_join_with_wrong_concrete_type() {
4554 let bytes = include_bytes!(
4555 "../../../baedeker-testdata/spec/invalid-validate/typed-ref-as-non-null-if-join-wrong-concrete-type.wasm",
4556 );
4557 let module = Module::decode(bytes).unwrap();
4558 let err = module.validate().unwrap_err();
4559 assert_eq!(err.offset, ByteOffset(46));
4560 assert!(matches!(
4561 err.kind,
4562 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
4563 if expected == vec![ValType::Ref(RefType::Typed {
4564 nullable: true,
4565 heap: crate::types::HeapType::Type(TypeIdx(1)),
4566 })] && found == vec![ValType::Ref(RefType::Typed {
4567 nullable: false,
4568 heap: crate::types::HeapType::Type(TypeIdx(0)),
4569 })]
4570 ));
4571 }
4572
4573 #[test]
4574 fn reject_typed_ref_as_non_null_function_result_wrong_concrete_type() {
4575 let bytes = include_bytes!(
4576 "../../../baedeker-testdata/spec/invalid-validate/typed-ref-as-non-null-function-result-wrong-concrete-type.wasm",
4577 );
4578 let module = Module::decode(bytes).unwrap();
4579 let err = module.validate().unwrap_err();
4580 assert_eq!(err.offset, ByteOffset(40));
4581 assert!(matches!(
4582 err.kind,
4583 ValidationErrorKind::FunctionResultTypeMismatch {
4584 expected,
4585 found,
4586 ..
4587 } if expected == vec![ValType::Ref(RefType::Typed {
4588 nullable: false,
4589 heap: crate::types::HeapType::Type(TypeIdx(1)),
4590 })] && found == vec![ValType::Ref(RefType::Typed {
4591 nullable: false,
4592 heap: crate::types::HeapType::Type(TypeIdx(0)),
4593 })]
4594 ));
4595 }
4596
4597 #[test]
4598 fn validate_typed_br_if_to_loop_param_nullable_official_case() {
4599 let bytes = include_bytes!(
4600 "../../../baedeker-testdata/spec/valid/typed-br-if-to-loop-param-nullable.wasm",
4601 );
4602 let module = Module::decode(bytes).unwrap();
4603 module.validate().unwrap();
4604 }
4605
4606 #[test]
4607 fn reject_typed_br_if_to_loop_param_nullability_mismatch() {
4608 let bytes = include_bytes!(
4609 "../../../baedeker-testdata/spec/invalid-validate/typed-br-if-to-loop-param-nullability-mismatch.wasm",
4610 );
4611 let module = Module::decode(bytes).unwrap();
4612 let err = module.validate().unwrap_err();
4613 assert_eq!(err.offset, ByteOffset(72));
4614 assert!(matches!(
4615 err.kind,
4616 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
4617 if label == crate::types::LabelIdx(0)
4618 && expected == vec![ValType::Ref(RefType::Typed {
4619 nullable: false,
4620 heap: crate::types::HeapType::Type(TypeIdx(0)),
4621 })]
4622 && found == vec![ValType::Ref(RefType::Typed {
4623 nullable: true,
4624 heap: crate::types::HeapType::Type(TypeIdx(0)),
4625 })]
4626 ));
4627 }
4628
4629 #[test]
4630 fn validate_br_on_null() {
4631 let bytes = [
4632 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x6F,
4633 0x01, 0x6F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0E, 0x01, 0x0C, 0x00, 0x02, 0x40, 0x20,
4634 0x00, 0xD5, 0x00, 0x0F, 0x0B, 0xD0, 0x6F, 0x0B,
4635 ];
4636 let module = Module::decode(&bytes).unwrap();
4637 module.validate().unwrap();
4638 }
4639
4640 #[test]
4641 fn reject_br_on_null_with_non_ref_input() {
4642 let bytes = [
4643 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x01, 0x7F,
4644 0x00, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0xD5, 0x00,
4645 0x1A, 0x0B,
4646 ];
4647 let module = Module::decode(&bytes).unwrap();
4648 let err = module.validate().unwrap_err();
4649 assert_eq!(err.offset, ByteOffset(26));
4650 assert!(matches!(
4651 err.kind,
4652 ValidationErrorKind::TypeMismatch {
4653 op: "br_on_null",
4654 expected: ValType::Ref(RefType::ExternRef),
4655 found: ValType::Num(crate::types::NumType::I32),
4656 }
4657 ));
4658 }
4659
4660 #[test]
4661 fn validate_typed_br_on_null_fallthrough_to_call_ref_with_equivalent_signature() {
4662 let bytes = include_bytes!(
4663 "../../../baedeker-testdata/spec/valid/typed-br-on-null-call-ref-equivalent-signature.wasm",
4664 );
4665 let module = Module::decode(bytes).unwrap();
4666 module.validate().unwrap();
4667 }
4668
4669 #[test]
4670 fn validate_br_on_null_unreachable_official_case() {
4671 let bytes =
4672 include_bytes!("../../../baedeker-testdata/spec/valid/br-on-null-unreachable.wasm",);
4673 let module = Module::decode(bytes).unwrap();
4674 module.validate().unwrap();
4675 }
4676
4677 #[test]
4678 fn reject_typed_br_on_null_fallthrough_to_call_ref_with_wrong_concrete_type() {
4679 let bytes = include_bytes!(
4680 "../../../baedeker-testdata/spec/invalid-validate/typed-br-on-null-call-ref-wrong-concrete-type.wasm",
4681 );
4682 let module = Module::decode(bytes).unwrap();
4683 let err = module.validate().unwrap_err();
4684 assert_eq!(err.offset, ByteOffset(60));
4685 assert!(matches!(
4686 err.kind,
4687 ValidationErrorKind::TypeMismatch { op, expected, found }
4688 if op == "call_ref"
4689 && expected == ValType::Ref(RefType::Typed {
4690 nullable: true,
4691 heap: crate::types::HeapType::Type(TypeIdx(1)),
4692 })
4693 && found == ValType::Ref(RefType::Typed {
4694 nullable: false,
4695 heap: crate::types::HeapType::Type(TypeIdx(0)),
4696 })
4697 ));
4698 }
4699
4700 #[test]
4701 fn reject_br_on_null_stack_mismatch_official_case() {
4702 let bytes = include_bytes!(
4703 "../../../baedeker-testdata/spec/invalid-validate/br-on-null-stack-mismatch.wasm",
4704 );
4705 let module = Module::decode(bytes).unwrap();
4706 let err = module.validate().unwrap_err();
4707 assert_eq!(err.offset, ByteOffset(47));
4708 assert!(matches!(
4709 err.kind,
4710 ValidationErrorKind::TypeMismatch { op, expected, found }
4711 if op == "stack"
4712 && expected == ValType::Ref(RefType::Typed {
4713 nullable: true,
4714 heap: crate::types::HeapType::Type(TypeIdx(0)),
4715 })
4716 && found == ValType::Ref(RefType::FuncRef)
4717 ));
4718 }
4719
4720 #[test]
4721 fn reject_typed_br_on_null_block_result_wrong_concrete_type() {
4722 let bytes = include_bytes!(
4723 "../../../baedeker-testdata/spec/invalid-validate/typed-br-on-null-block-result-wrong-concrete-type.wasm",
4724 );
4725 let module = Module::decode(bytes).unwrap();
4726 let err = module.validate().unwrap_err();
4727 assert_eq!(err.offset, ByteOffset(57));
4728 assert!(matches!(
4729 err.kind,
4730 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
4731 if expected == vec![ValType::Ref(RefType::Typed {
4732 nullable: true,
4733 heap: crate::types::HeapType::Type(TypeIdx(1)),
4734 })] && found == vec![ValType::Ref(RefType::Typed {
4735 nullable: true,
4736 heap: crate::types::HeapType::Type(TypeIdx(0)),
4737 })]
4738 ));
4739 }
4740
4741 #[test]
4742 fn validate_br_on_non_null() {
4743 let bytes = [
4744 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x6F,
4745 0x01, 0x6F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0F, 0x01, 0x0D, 0x00, 0x02, 0x64, 0x6F,
4746 0x20, 0x00, 0xD6, 0x00, 0xD0, 0x6F, 0x0F, 0x0B, 0x0B,
4747 ];
4748 let module = Module::decode(&bytes).unwrap();
4749 module.validate().unwrap();
4750 }
4751
4752 #[test]
4753 fn reject_br_on_non_null_with_non_ref_target() {
4754 let bytes = [
4755 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x01, 0x6F,
4756 0x00, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0D, 0x01, 0x0B, 0x00, 0x02, 0x7F, 0x20, 0x00,
4757 0xD6, 0x00, 0x41, 0x00, 0x0B, 0x0B,
4758 ];
4759 let module = Module::decode(&bytes).unwrap();
4760 let err = module.validate().unwrap_err();
4761 assert_eq!(err.offset, ByteOffset(28));
4762 assert!(matches!(
4763 err.kind,
4764 ValidationErrorKind::InvalidBrOnNonNullTarget {
4765 label: crate::types::LabelIdx(0),
4766 found,
4767 } if found == vec![ValType::Num(crate::types::NumType::I32)]
4768 ));
4769 }
4770
4771 #[test]
4772 fn validate_typed_br_on_non_null_branch_to_call_ref_with_equivalent_signature() {
4773 let bytes = include_bytes!(
4774 "../../../baedeker-testdata/spec/valid/typed-br-on-non-null-call-ref-equivalent-signature.wasm",
4775 );
4776 let module = Module::decode(bytes).unwrap();
4777 module.validate().unwrap();
4778 }
4779
4780 #[test]
4781 fn validate_br_on_non_null_ref_as_non_null_official_case() {
4782 let bytes = include_bytes!(
4783 "../../../baedeker-testdata/spec/valid/br-on-non-null-ref-as-non-null.wasm",
4784 );
4785 let module = Module::decode(bytes).unwrap();
4786 module.validate().unwrap();
4787 }
4788
4789 #[test]
4790 fn validate_br_on_non_null_unreachable_official_case() {
4791 let bytes = include_bytes!(
4792 "../../../baedeker-testdata/spec/valid/br-on-non-null-unreachable.wasm",
4793 );
4794 let module = Module::decode(bytes).unwrap();
4795 module.validate().unwrap();
4796 }
4797
4798 #[test]
4799 fn reject_typed_br_on_non_null_branch_to_call_ref_with_wrong_concrete_type() {
4800 let bytes = include_bytes!(
4801 "../../../baedeker-testdata/spec/invalid-validate/typed-br-on-non-null-call-ref-wrong-concrete-type.wasm",
4802 );
4803 let module = Module::decode(bytes).unwrap();
4804 let err = module.validate().unwrap_err();
4805 assert_eq!(err.offset, ByteOffset(53));
4806 assert!(matches!(
4807 err.kind,
4808 ValidationErrorKind::TypeMismatch { op, expected, found }
4809 if op == "br_on_non_null"
4810 && expected == ValType::Ref(RefType::Typed {
4811 nullable: true,
4812 heap: crate::types::HeapType::Type(TypeIdx(1)),
4813 })
4814 && found == ValType::Ref(RefType::Typed {
4815 nullable: true,
4816 heap: crate::types::HeapType::Type(TypeIdx(0)),
4817 })
4818 ));
4819 }
4820
4821 #[test]
4822 fn reject_br_on_non_null_stack_mismatch_official_case() {
4823 let bytes = include_bytes!(
4824 "../../../baedeker-testdata/spec/invalid-validate/br-on-non-null-stack-mismatch.wasm",
4825 );
4826 let module = Module::decode(bytes).unwrap();
4827 let err = module.validate().unwrap_err();
4828 assert_eq!(err.offset, ByteOffset(47));
4829 assert!(matches!(
4830 err.kind,
4831 ValidationErrorKind::TypeMismatch { op, expected, found }
4832 if op == "stack"
4833 && expected == ValType::Ref(RefType::Typed {
4834 nullable: true,
4835 heap: crate::types::HeapType::Type(TypeIdx(0)),
4836 })
4837 && found == ValType::Ref(RefType::FuncRef)
4838 ));
4839 }
4840
4841 #[test]
4842 fn reject_typed_br_on_non_null_block_result_wrong_concrete_type() {
4843 let bytes = include_bytes!(
4844 "../../../baedeker-testdata/spec/invalid-validate/typed-br-on-non-null-block-result-wrong-concrete-type.wasm",
4845 );
4846 let module = Module::decode(bytes).unwrap();
4847 let err = module.validate().unwrap_err();
4848 assert_eq!(err.offset, ByteOffset(63));
4849 assert!(matches!(
4850 err.kind,
4851 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
4852 if expected == vec![ValType::Ref(RefType::Typed {
4853 nullable: false,
4854 heap: crate::types::HeapType::Type(TypeIdx(1)),
4855 })] && found == vec![ValType::Ref(RefType::Typed {
4856 nullable: false,
4857 heap: crate::types::HeapType::Type(TypeIdx(0)),
4858 })]
4859 ));
4860 }
4861
4862 #[test]
4863 fn validate_global_init_expr_from_imported_const_global() {
4864 let bytes = [
4865 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, b'e', b'n',
4866 b'v', 0x01, b'g', 0x03, 0x7F, 0x00, 0x06, 0x06, 0x01, 0x7F, 0x00, 0x23, 0x00, 0x0B,
4867 ];
4868 let module = Module::decode(&bytes).unwrap();
4869 module.validate().unwrap();
4870 }
4871
4872 #[test]
4873 fn validate_global_init_expr_from_defined_const_global() {
4874 let bytes = [
4875 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x06, 0x0B, 0x02, 0x7F, 0x00, 0x41,
4876 0x00, 0x0B, 0x7F, 0x00, 0x23, 0x00, 0x0B,
4877 ];
4878 let module = Module::decode(&bytes).unwrap();
4879 module.validate().unwrap();
4880 }
4881
4882 #[test]
4883 fn validate_global_init_expr_with_extended_const_arithmetic() {
4884 let bytes = [
4885 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, 0x65, 0x6E,
4886 0x76, 0x01, 0x67, 0x03, 0x7F, 0x00, 0x06, 0x09, 0x01, 0x7F, 0x00, 0x23, 0x00, 0x41,
4887 0x2A, 0x6A, 0x0B,
4888 ];
4889 let module = Module::decode(&bytes).unwrap();
4890 module.validate().unwrap();
4891 }
4892
4893 #[test]
4894 fn validate_reference_global_init_exprs() {
4895 let bytes = [
4896 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4897 0x03, 0x02, 0x01, 0x00, 0x06, 0x0B, 0x02, 0x6F, 0x00, 0xD0, 0x6F, 0x0B, 0x70, 0x00,
4898 0xD2, 0x00, 0x0B, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
4899 ];
4900 let module = Module::decode(&bytes).unwrap();
4901 module.validate().unwrap();
4902 }
4903
4904 #[test]
4905 fn validate_ref_func_declared_by_exported_import() {
4906 let bytes = [
4907 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4908 0x02, 0x09, 0x01, 0x03, b'e', b'n', b'v', 0x01, b'f', 0x00, 0x00, 0x03, 0x02, 0x01,
4909 0x00, 0x07, 0x05, 0x01, 0x01, b'f', 0x00, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xD2,
4910 0x00, 0x1A, 0x0B,
4911 ];
4912 let module = Module::decode(&bytes).unwrap();
4913 module.validate().unwrap();
4914 }
4915
4916 #[test]
4917 fn validate_ref_func_declared_by_declarative_element() {
4918 let bytes = [
4919 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4920 0x03, 0x03, 0x02, 0x00, 0x00, 0x09, 0x05, 0x01, 0x03, 0x00, 0x01, 0x00, 0x0A, 0x0A,
4921 0x02, 0x02, 0x00, 0x0B, 0x05, 0x00, 0xD2, 0x00, 0x1A, 0x0B,
4922 ];
4923 let module = Module::decode(&bytes).unwrap();
4924 module.validate().unwrap();
4925 }
4926
4927 #[test]
4928 fn reject_undeclared_ref_func_self_reference() {
4929 let bytes = [
4930 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4931 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xD2, 0x00, 0x1A, 0x0B,
4932 ];
4933 let module = Module::decode(&bytes).unwrap();
4934 let err = module.validate().unwrap_err();
4935 assert!(matches!(
4936 err.kind,
4937 ValidationErrorKind::UndeclaredFuncRef {
4938 idx: crate::types::FuncIdx(0)
4939 }
4940 ));
4941 }
4942
4943 #[test]
4944 fn reject_ref_func_when_start_is_only_declaration_source() {
4945 let bytes = [
4946 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
4947 0x03, 0x02, 0x01, 0x00, 0x08, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xD2, 0x00,
4948 0x1A, 0x0B,
4949 ];
4950 let module = Module::decode(&bytes).unwrap();
4951 let err = module.validate().unwrap_err();
4952 assert!(matches!(
4953 err.kind,
4954 ValidationErrorKind::UndeclaredFuncRef {
4955 idx: crate::types::FuncIdx(0)
4956 }
4957 ));
4958 }
4959
4960 #[test]
4961 fn reject_global_init_expr_from_mutable_imported_global() {
4962 let bytes = [
4963 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, b'e', b'n',
4964 b'v', 0x01, b'g', 0x03, 0x7F, 0x01, 0x06, 0x06, 0x01, 0x7F, 0x00, 0x23, 0x00, 0x0B,
4965 ];
4966 let module = Module::decode(&bytes).unwrap();
4967 let err = module.validate().unwrap_err();
4968 assert_eq!(err.offset, ByteOffset(25));
4969 assert!(matches!(
4970 err.kind,
4971 ValidationErrorKind::MutableGlobalInInitExpr {
4972 idx: crate::types::GlobalIdx(0)
4973 }
4974 ));
4975 }
4976
4977 #[test]
4978 fn reject_global_init_expr_type_mismatch() {
4979 let bytes = [
4980 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x06, 0x06, 0x01, 0x7E, 0x00, 0x41,
4981 0x2A, 0x0B,
4982 ];
4983 let module = Module::decode(&bytes).unwrap();
4984 let err = module.validate().unwrap_err();
4985 assert_eq!(err.offset, ByteOffset(13));
4986 assert!(matches!(
4987 err.kind,
4988 ValidationErrorKind::GlobalInitTypeMismatch {
4989 expected: ValType::Num(crate::types::NumType::I64),
4990 found: ValType::Num(crate::types::NumType::I32),
4991 }
4992 ));
4993 }
4994
4995 #[test]
4996 fn reject_non_constant_global_init_expr() {
4997 let bytes = [
4998 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x06, 0x08, 0x01, 0x7F, 0x00, 0x41,
4999 0x01, 0x41, 0x02, 0x0B,
5000 ];
5001 let module = Module::decode(&bytes).unwrap();
5002 let err = module.validate().unwrap_err();
5003 assert_eq!(err.offset, ByteOffset(13));
5004 assert!(matches!(
5005 err.kind,
5006 ValidationErrorKind::InvalidGlobalInitExpr
5007 ));
5008 }
5009
5010 #[test]
5011 fn validate_active_data_offset_from_imported_const_global() {
5012 let bytes = [
5013 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, b'e', b'n',
5014 b'v', 0x01, b'g', 0x03, 0x7F, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0B, 0x07, 0x01,
5015 0x00, 0x23, 0x00, 0x0B, 0x01, 0xAA,
5016 ];
5017 let module = Module::decode(&bytes).unwrap();
5018 module.validate().unwrap();
5019 }
5020
5021 #[test]
5022 fn validate_active_data_offset_from_defined_const_global() {
5023 let bytes = [
5024 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06,
5025 0x06, 0x01, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x0B, 0x07, 0x01, 0x00, 0x23, 0x00, 0x0B,
5026 0x01, 0x61,
5027 ];
5028 let module = Module::decode(&bytes).unwrap();
5029 module.validate().unwrap();
5030 }
5031
5032 #[test]
5033 fn validate_active_data_offset_with_extended_const_arithmetic() {
5034 let bytes = [
5035 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, 0x65, 0x6E,
5036 0x76, 0x01, 0x67, 0x03, 0x7F, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0B, 0x10, 0x01,
5037 0x00, 0x41, 0x02, 0x23, 0x00, 0x41, 0x01, 0x6B, 0x41, 0x02, 0x6A, 0x6C, 0x0B, 0x01,
5038 0x61,
5039 ];
5040 let module = Module::decode(&bytes).unwrap();
5041 module.validate().unwrap();
5042 }
5043
5044 #[test]
5045 fn validate_element_expr_from_imported_const_ref_global() {
5046 let bytes = [
5047 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x01, 0x03, b'e', b'n',
5048 b'v', 0x01, b'g', 0x03, 0x6F, 0x00, 0x04, 0x04, 0x01, 0x6F, 0x00, 0x01, 0x09, 0x0B,
5049 0x01, 0x06, 0x00, 0x41, 0x00, 0x0B, 0x6F, 0x01, 0x23, 0x00, 0x0B,
5050 ];
5051 let module = Module::decode(&bytes).unwrap();
5052 module.validate().unwrap();
5053 }
5054
5055 #[test]
5056 fn validate_active_element_offset_from_defined_const_global() {
5057 let bytes = [
5058 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5059 0x03, 0x02, 0x01, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01, 0x06, 0x06, 0x01, 0x7F,
5060 0x00, 0x41, 0x00, 0x0B, 0x09, 0x07, 0x01, 0x00, 0x23, 0x00, 0x0B, 0x01, 0x00, 0x0A,
5061 0x04, 0x01, 0x02, 0x00, 0x0B,
5062 ];
5063 let module = Module::decode(&bytes).unwrap();
5064 module.validate().unwrap();
5065 }
5066
5067 #[test]
5068 fn validate_active_element_offset_with_extended_const_arithmetic() {
5069 let bytes = [
5070 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5071 0x02, 0x0A, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x7F, 0x00, 0x03, 0x02,
5072 0x01, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x08, 0x09, 0x14, 0x01, 0x06, 0x00, 0x41,
5073 0x02, 0x23, 0x00, 0x41, 0x01, 0x6B, 0x41, 0x02, 0x6A, 0x6C, 0x0B, 0x70, 0x01, 0xD2,
5074 0x00, 0x0B, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
5075 ];
5076 let module = Module::decode(&bytes).unwrap();
5077 module.validate().unwrap();
5078 }
5079
5080 #[test]
5081 fn validate_memory_size_and_grow_for_imported_memory() {
5082 let bytes = [
5083 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5084 0x7F, 0x02, 0x0C, 0x01, 0x03, b'e', b'n', b'v', 0x03, b'm', b'e', b'm', 0x02, 0x00,
5085 0x01, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0B, 0x01, 0x09, 0x00, 0x41, 0x01, 0x40, 0x00,
5086 0x1A, 0x3F, 0x00, 0x0B,
5087 ];
5088 let module = Module::decode(&bytes).unwrap();
5089 module.validate().unwrap();
5090 }
5091
5092 #[test]
5093 fn validate_memory_size_and_grow_for_defined_memory() {
5094 let bytes = [
5095 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5096 0x7F, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0B, 0x01, 0x09,
5097 0x00, 0x41, 0x01, 0x40, 0x00, 0x1A, 0x3F, 0x00, 0x0B,
5098 ];
5099 let module = Module::decode(&bytes).unwrap();
5100 module.validate().unwrap();
5101 }
5102
5103 #[test]
5104 fn validate_memory_size_and_grow_for_nonzero_memory_index() {
5105 let bytes = [
5106 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5107 0x7F, 0x02, 0x0C, 0x01, 0x03, b'e', b'n', b'v', 0x03, b'm', b'e', b'm', 0x02, 0x00,
5108 0x01, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0B, 0x01, 0x09,
5109 0x00, 0x41, 0x01, 0x40, 0x01, 0x1A, 0x3F, 0x01, 0x0B,
5110 ];
5111 let module = Module::decode(&bytes).unwrap();
5112 module.validate().unwrap();
5113 }
5114
5115 #[test]
5116 fn validate_i32_load_and_store_for_defined_memory() {
5117 let bytes = [
5118 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5119 0x7F, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x10, 0x01, 0x0E,
5120 0x00, 0x41, 0x00, 0x41, 0x2A, 0x36, 0x02, 0x00, 0x41, 0x00, 0x28, 0x02, 0x00, 0x0B,
5121 ];
5122 let module = Module::decode(&bytes).unwrap();
5123 module.validate().unwrap();
5124 }
5125
5126 #[test]
5127 fn validate_i32_load_and_store_for_nonzero_memory_index() {
5128 let bytes = [
5129 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x01,
5130 0x7F, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x05, 0x05, 0x02, 0x00, 0x01,
5131 0x00, 0x01, 0x0A, 0x15, 0x02, 0x08, 0x00, 0x41, 0x00, 0x28, 0x42, 0x01, 0x00, 0x0B,
5132 0x0A, 0x00, 0x41, 0x00, 0x41, 0x01, 0x36, 0x42, 0x01, 0x00, 0x0B,
5133 ];
5134 let module = Module::decode(&bytes).unwrap();
5135 module.validate().unwrap();
5136 }
5137
5138 #[test]
5139 fn validate_narrow_memory_ops_for_defined_memory() {
5140 let bytes = [
5141 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, 0x00, 0x01,
5142 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x03, 0x03, 0x02, 0x00, 0x01, 0x05, 0x03, 0x01, 0x00,
5143 0x01, 0x0A, 0x1D, 0x02, 0x0D, 0x00, 0x41, 0x00, 0x2C, 0x00, 0x00, 0x1A, 0x41, 0x00,
5144 0x2F, 0x01, 0x00, 0x0B, 0x0D, 0x00, 0x41, 0x00, 0x30, 0x00, 0x00, 0x1A, 0x41, 0x00,
5145 0x35, 0x02, 0x00, 0x0B,
5146 ];
5147 let module = Module::decode(&bytes).unwrap();
5148 module.validate().unwrap();
5149 }
5150
5151 #[test]
5152 fn validate_narrow_memory_stores_for_defined_memory() {
5153 let bytes = [
5154 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5155 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x27, 0x01, 0x25, 0x00,
5156 0x41, 0x00, 0x41, 0x7F, 0x3A, 0x00, 0x00, 0x41, 0x00, 0x41, 0x7F, 0x3B, 0x01, 0x00,
5157 0x41, 0x00, 0x42, 0x01, 0x3C, 0x00, 0x00, 0x41, 0x00, 0x42, 0x01, 0x3D, 0x01, 0x00,
5158 0x41, 0x00, 0x42, 0x01, 0x3E, 0x02, 0x00, 0x0B,
5159 ];
5160 let module = Module::decode(&bytes).unwrap();
5161 module.validate().unwrap();
5162 }
5163
5164 #[test]
5165 fn validate_v128_load_and_store_for_defined_memory() {
5166 let bytes = [
5167 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x01,
5168 0x7B, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01,
5169 0x0A, 0x25, 0x02, 0x08, 0x00, 0x41, 0x00, 0xFD, 0x00, 0x04, 0x00, 0x0B, 0x1A, 0x00,
5170 0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0B, 0x04, 0x00, 0x0B,
5172 ];
5173 let module = Module::decode(&bytes).unwrap();
5174 module.validate().unwrap();
5175 }
5176
5177 #[test]
5178 fn validate_v128_load_and_store_for_nonzero_memory_index() {
5179 let bytes = [
5180 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x01,
5181 0x7B, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x05, 0x05, 0x02, 0x00, 0x01,
5182 0x00, 0x01, 0x0A, 0x27, 0x02, 0x09, 0x00, 0x41, 0x00, 0xFD, 0x00, 0x44, 0x01, 0x00,
5183 0x0B, 0x1B, 0x00, 0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0B, 0x44, 0x01, 0x00,
5185 0x0B,
5186 ];
5187 let module = Module::decode(&bytes).unwrap();
5188 module.validate().unwrap();
5189 }
5190
5191 #[test]
5192 fn validate_data_segments_and_bulk_memory_ops() {
5193 let bytes = [
5194 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5195 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x24, 0x01, 0x22, 0x00,
5196 0x41, 0x00, 0x41, 0x00, 0x41, 0x02, 0xFC, 0x08, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x41,
5197 0x00, 0x41, 0x00, 0x41, 0x02, 0xFC, 0x0A, 0x00, 0x00, 0x41, 0x00, 0x41, 0x7F, 0x41,
5198 0x02, 0xFC, 0x0B, 0x00, 0x0B, 0x0B, 0x08, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x02, 0xAA,
5199 0xBB, 0x0C, 0x01, 0x01,
5200 ];
5201 let module = Module::decode(&bytes).unwrap();
5202 module.validate().unwrap();
5203 }
5204
5205 #[test]
5206 fn reject_unknown_data_index_in_memory_init() {
5207 let bytes = [
5208 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5209 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0E, 0x01, 0x0C, 0x00,
5210 0x41, 0x00, 0x41, 0x00, 0x41, 0x01, 0xFC, 0x08, 0x00, 0x00, 0x0B, 0x0C, 0x01, 0x00,
5211 ];
5212 let module = Module::decode(&bytes).unwrap();
5213 let err = module.validate().unwrap_err();
5214 assert!(matches!(
5215 err.kind,
5216 ValidationErrorKind::UnknownDataIdx {
5217 idx: crate::types::DataIdx(0),
5218 available: 0,
5219 }
5220 ));
5221 }
5222
5223 #[test]
5224 fn validate_v128_lane_memory_ops() {
5225 let bytes = [
5226 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5227 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x37, 0x01, 0x35, 0x00,
5228 0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x54, 0x00, 0x00, 0x0F, 0x1A, 0x41, 0x00,
5230 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5231 0x00, 0x00, 0x00, 0x00, 0xFD, 0x58, 0x00, 0x00, 0x0F, 0x0B,
5232 ];
5233 let module = Module::decode(&bytes).unwrap();
5234 module.validate().unwrap();
5235 }
5236
5237 #[test]
5238 fn reject_v128_load16_lane_with_invalid_lane_index() {
5239 let bytes = [
5240 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5241 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x1E, 0x01, 0x1C, 0x00,
5242 0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x55, 0x01, 0x00, 0x08, 0x1A, 0x0B,
5244 ];
5245 let module = Module::decode(&bytes).unwrap();
5246 let err = module.validate().unwrap_err();
5247 assert!(matches!(
5248 err.kind,
5249 ValidationErrorKind::InvalidSimdLaneIdx {
5250 op: "v128.load16_lane",
5251 max: 7,
5252 found: 8,
5253 }
5254 ));
5255 }
5256
5257 #[test]
5258 fn reject_i64_load32_with_invalid_memarg_align() {
5259 let bytes = [
5260 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5261 0x7E, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0A, 0x01, 0x08,
5262 0x00, 0x41, 0x00, 0x35, 0x03, 0x00, 0x1A, 0x0B,
5263 ];
5264 let module = Module::decode(&bytes).unwrap();
5265 let err = module.validate().unwrap_err();
5266 assert!(matches!(
5267 err.kind,
5268 ValidationErrorKind::InvalidMemArgAlign {
5269 op: "i64.load32",
5270 max: 2,
5271 found: 3,
5272 }
5273 ));
5274 }
5275
5276 #[test]
5277 fn reject_i64_store32_with_wrong_value_type() {
5278 let bytes = [
5279 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5280 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0B, 0x01, 0x09, 0x00,
5281 0x41, 0x00, 0x41, 0x01, 0x3E, 0x02, 0x00, 0x0B,
5282 ];
5283 let module = Module::decode(&bytes).unwrap();
5284 let err = module.validate().unwrap_err();
5285 assert!(matches!(
5286 err.kind,
5287 ValidationErrorKind::TypeMismatch {
5288 op: "i64.store32",
5289 expected: ValType::Num(crate::types::NumType::I64),
5290 found: ValType::Num(crate::types::NumType::I32),
5291 }
5292 ));
5293 }
5294
5295 #[test]
5296 fn reject_i32_load_with_invalid_memarg_align() {
5297 let bytes = [
5298 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5299 0x7F, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0C, 0x01, 0x0A,
5300 0x00, 0x41, 0x00, 0x28, 0x03, 0x00, 0x1A, 0x41, 0x00, 0x0B,
5301 ];
5302 let module = Module::decode(&bytes).unwrap();
5303 let err = module.validate().unwrap_err();
5304 assert!(matches!(
5305 err.kind,
5306 ValidationErrorKind::InvalidMemArgAlign {
5307 op: "i32.load",
5308 max: 2,
5309 found: 3,
5310 }
5311 ));
5312 }
5313
5314 #[test]
5315 fn reject_i32_store_with_wrong_value_type() {
5316 let bytes = [
5317 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5318 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0B, 0x01, 0x09, 0x00,
5319 0x41, 0x00, 0x42, 0x01, 0x36, 0x02, 0x00, 0x0B,
5320 ];
5321 let module = Module::decode(&bytes).unwrap();
5322 let err = module.validate().unwrap_err();
5323 assert!(matches!(
5324 err.kind,
5325 ValidationErrorKind::TypeMismatch {
5326 op: "i32.store",
5327 expected: ValType::Num(crate::types::NumType::I32),
5328 found: ValType::Num(crate::types::NumType::I64),
5329 }
5330 ));
5331 }
5332
5333 #[test]
5334 fn reject_unknown_imported_global_index() {
5335 let bytes = [
5336 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5337 0x03, 0x02, 0x01, 0x00, 0x0A, 0x06, 0x01, 0x04, 0x00, 0x23, 0x00, 0x0B,
5338 ];
5339 let module = Module::decode(&bytes).unwrap();
5340 let err = module.validate().unwrap_err();
5341 assert!(matches!(
5342 err.kind,
5343 ValidationErrorKind::UnknownGlobalIdx {
5344 idx: crate::types::GlobalIdx(0),
5345 available: 0,
5346 }
5347 ));
5348 }
5349
5350 #[test]
5351 fn reject_unknown_imported_memory_index() {
5352 let bytes = [
5353 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5354 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x06, 0x01, 0x04, 0x00, 0x3F, 0x00, 0x0B,
5355 ];
5356 let module = Module::decode(&bytes).unwrap();
5357 let err = module.validate().unwrap_err();
5358 assert!(matches!(
5359 err.kind,
5360 ValidationErrorKind::UnknownMemIdx {
5361 idx: crate::types::MemIdx(0),
5362 available: 0,
5363 }
5364 ));
5365 }
5366
5367 #[test]
5368 fn validate_i64_add() {
5369 let bytes = [
5370 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
5371 0x7E, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x42, 0x01, 0x42, 0x02,
5372 0x7C, 0x0B,
5373 ];
5374 let module = Module::decode(&bytes).unwrap();
5375 module.validate().unwrap();
5376 }
5377
5378 #[test]
5379 fn reject_if_result_without_else() {
5380 let bytes = [
5381 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5382 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0C, 0x01, 0x0A, 0x00, 0x41, 0x01, 0x04, 0x7F, 0x41,
5383 0x02, 0x0B, 0x1A, 0x0B,
5384 ];
5385 let module = Module::decode(&bytes).unwrap();
5386 let err = module.validate().unwrap_err();
5387 assert!(matches!(
5388 err.kind,
5389 ValidationErrorKind::MissingElseForResult
5390 ));
5391 }
5392
5393 #[test]
5394 fn map_unknown_opcode_into_validation_error() {
5395 let bytes = [
5396 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5397 0x03, 0x02, 0x01, 0x00, 0x0A, 0x05, 0x01, 0x03, 0x00, 0xFF, 0x0B,
5398 ];
5399 let module = Module::decode(&bytes).unwrap();
5400 let err = module.validate().unwrap_err();
5401 assert_eq!(err.offset, ByteOffset(23));
5402 assert!(matches!(
5403 err.kind,
5404 ValidationErrorKind::Decode {
5405 context: crate::error::DecodeContext::CodeSection,
5406 kind: crate::error::DecodeErrorKind::UnknownOpcode { byte: 0xFF },
5407 }
5408 ));
5409 }
5410
5411 #[test]
5412 fn map_unterminated_body_into_validation_error() {
5413 let bytes = [
5414 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5415 0x03, 0x02, 0x01, 0x00, 0x0A, 0x05, 0x01, 0x03, 0x00, 0x20, 0x00,
5416 ];
5417 let module = Module::decode(&bytes).unwrap();
5418 let err = module.validate().unwrap_err();
5419 assert_eq!(err.offset, ByteOffset(25));
5420 assert!(matches!(
5421 err.kind,
5422 ValidationErrorKind::Decode {
5423 context: crate::error::DecodeContext::CodeSection,
5424 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5425 }
5426 ));
5427 }
5428
5429 #[test]
5430 fn map_truncated_call_ref_immediate_into_validation_error() {
5431 let bytes = include_bytes!(
5432 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-call-ref-typeidx.wasm",
5433 );
5434 let module = Module::decode(bytes).unwrap();
5435 let err = module.validate().unwrap_err();
5436 assert_eq!(err.offset, ByteOffset(24));
5437 assert!(matches!(
5438 err.kind,
5439 ValidationErrorKind::Decode {
5440 context: crate::error::DecodeContext::CodeSection,
5441 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5442 }
5443 ));
5444 }
5445
5446 #[test]
5447 fn map_truncated_return_call_ref_immediate_into_validation_error() {
5448 let bytes = include_bytes!(
5449 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-return-call-ref-typeidx.wasm",
5450 );
5451 let module = Module::decode(bytes).unwrap();
5452 let err = module.validate().unwrap_err();
5453 assert_eq!(err.offset, ByteOffset(24));
5454 assert!(matches!(
5455 err.kind,
5456 ValidationErrorKind::Decode {
5457 context: crate::error::DecodeContext::CodeSection,
5458 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5459 }
5460 ));
5461 }
5462
5463 #[test]
5464 fn map_truncated_br_on_null_immediate_into_validation_error() {
5465 let bytes = include_bytes!(
5466 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-br-on-null-labelidx.wasm",
5467 );
5468 let module = Module::decode(bytes).unwrap();
5469 let err = module.validate().unwrap_err();
5470 assert_eq!(err.offset, ByteOffset(24));
5471 assert!(matches!(
5472 err.kind,
5473 ValidationErrorKind::Decode {
5474 context: crate::error::DecodeContext::CodeSection,
5475 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5476 }
5477 ));
5478 }
5479
5480 #[test]
5481 fn map_truncated_br_on_non_null_immediate_into_validation_error() {
5482 let bytes = include_bytes!(
5483 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-br-on-non-null-labelidx.wasm",
5484 );
5485 let module = Module::decode(bytes).unwrap();
5486 let err = module.validate().unwrap_err();
5487 assert_eq!(err.offset, ByteOffset(24));
5488 assert!(matches!(
5489 err.kind,
5490 ValidationErrorKind::Decode {
5491 context: crate::error::DecodeContext::CodeSection,
5492 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5493 }
5494 ));
5495 }
5496
5497 #[test]
5498 fn map_truncated_ref_null_heaptype_into_validation_error() {
5499 let bytes = include_bytes!(
5500 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-ref-null-heaptype.wasm",
5501 );
5502 let module = Module::decode(bytes).unwrap();
5503 let err = module.validate().unwrap_err();
5504 assert_eq!(err.offset, ByteOffset(24));
5505 assert!(matches!(
5506 err.kind,
5507 ValidationErrorKind::Decode {
5508 context: crate::error::DecodeContext::CodeSection,
5509 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5510 }
5511 ));
5512 }
5513
5514 #[test]
5515 fn map_truncated_typed_block_result_heaptype_into_validation_error() {
5516 let bytes = include_bytes!(
5517 "../../../baedeker-testdata/spec/invalid-validate/body-decode-truncated-block-result-heaptype.wasm",
5518 );
5519 let module = Module::decode(bytes).unwrap();
5520 let err = module.validate().unwrap_err();
5521 assert_eq!(err.offset, ByteOffset(25));
5522 assert!(matches!(
5523 err.kind,
5524 ValidationErrorKind::Decode {
5525 context: crate::error::DecodeContext::CodeSection,
5526 kind: crate::error::DecodeErrorKind::UnexpectedEof,
5527 }
5528 ));
5529 }
5530
5531 #[test]
5532 fn report_branch_type_mismatch_with_label_types() {
5533 let bytes = [
5534 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5535 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0C, 0x01, 0x0A, 0x00, 0x02, 0x7F, 0x42, 0x00, 0x0C,
5536 0x00, 0x0B, 0x1A, 0x0B,
5537 ];
5538 let module = Module::decode(&bytes).unwrap();
5539 let err = module.validate().unwrap_err();
5540 assert_eq!(err.offset, ByteOffset(27));
5541 assert!(matches!(
5542 err.kind,
5543 ValidationErrorKind::BranchTypeMismatch {
5544 label: crate::types::LabelIdx(0),
5545 expected,
5546 found,
5547 } if expected == vec![ValType::Num(crate::types::NumType::I32)]
5548 && found == vec![ValType::Num(crate::types::NumType::I64)]
5549 ));
5550 }
5551
5552 #[test]
5553 fn report_control_result_type_mismatch_at_end() {
5554 let bytes = [
5555 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5556 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x01, 0x08, 0x00, 0x02, 0x7F, 0x42, 0x00, 0x0B,
5557 0x1A, 0x0B,
5558 ];
5559 let module = Module::decode(&bytes).unwrap();
5560 let err = module.validate().unwrap_err();
5561 assert_eq!(err.offset, ByteOffset(27));
5562 assert!(matches!(
5563 err.kind,
5564 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
5565 if expected == vec![ValType::Num(crate::types::NumType::I32)]
5566 && found == vec![ValType::Num(crate::types::NumType::I64)]
5567 ));
5568 }
5569
5570 #[test]
5571 fn reject_block_end_with_extra_operand() {
5572 let bytes = [
5573 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5574 0x03, 0x02, 0x01, 0x00, 0x0A, 0x10, 0x01, 0x0E, 0x00, 0x02, 0x40, 0x43, 0x00, 0x00,
5575 0x00, 0x00, 0x41, 0x01, 0x0D, 0x00, 0x0B, 0x0B,
5576 ];
5577 let module = Module::decode(&bytes).unwrap();
5578 let err = module.validate().unwrap_err();
5579 assert_eq!(err.offset, ByteOffset(34));
5580 assert!(matches!(
5581 err.kind,
5582 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
5583 if expected.is_empty()
5584 && found == vec![ValType::Num(crate::types::NumType::F32)]
5585 ));
5586 }
5587
5588 #[test]
5589 fn reject_block_end_after_consuming_outer_operand() {
5590 let bytes = [
5591 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5592 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x00, 0x0A, 0x0D, 0x01, 0x0B, 0x00,
5593 0x41, 0x00, 0x02, 0x40, 0x28, 0x00, 0x00, 0x1A, 0x0B, 0x0B,
5594 ];
5595 let module = Module::decode(&bytes).unwrap();
5596 let err = module.validate().unwrap_err();
5597 assert_eq!(err.offset, ByteOffset(36));
5598 assert!(matches!(
5599 err.kind,
5600 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
5601 if expected.is_empty() && found.is_empty()
5602 ));
5603 }
5604
5605 #[test]
5606 fn reject_folded_syntax_equivalent_br_if_operand_use() {
5607 let bytes = [
5608 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
5609 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0D, 0x01, 0x0B, 0x00, 0x02, 0x40, 0x41, 0x01, 0x0D,
5610 0x00, 0x8C, 0x01, 0x0B, 0x0B,
5611 ];
5612 let module = Module::decode(&bytes).unwrap();
5613 let err = module.validate().unwrap_err();
5614 assert_eq!(err.offset, ByteOffset(29));
5615 assert!(matches!(
5616 err.kind,
5617 ValidationErrorKind::StackUnderflow { op, expected, .. }
5618 if op == "f32.unary"
5619 && expected == vec![ValType::Num(crate::types::NumType::F32)]
5620 ));
5621 }
5622
5623 #[test]
5624 fn validate_call_as_call_all_operands_official_case() {
5625 let bytes =
5626 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-call-all-operands.wasm",);
5627 let module = Module::decode(bytes).unwrap();
5628 module.validate().unwrap();
5629 }
5630
5631 #[test]
5632 fn validate_call_as_br_table_last_official_case() {
5633 let bytes =
5634 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-br-table-last.wasm");
5635 let module = Module::decode(bytes).unwrap();
5636 module.validate().unwrap();
5637 }
5638
5639 #[test]
5640 fn validate_call_as_call_indirect_last_official_case() {
5641 let bytes = include_bytes!(
5642 "../../../baedeker-testdata/spec/valid/call-as-call-indirect-last.wasm",
5643 );
5644 let module = Module::decode(bytes).unwrap();
5645 module.validate().unwrap();
5646 }
5647
5648 #[test]
5649 fn validate_call_as_memory_grow_value_official_case() {
5650 let bytes =
5651 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-memory-grow-value.wasm",);
5652 let module = Module::decode(bytes).unwrap();
5653 module.validate().unwrap();
5654 }
5655
5656 #[test]
5657 fn validate_call_as_local_tee_value_official_case() {
5658 let bytes =
5659 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-local-tee-value.wasm",);
5660 let module = Module::decode(bytes).unwrap();
5661 module.validate().unwrap();
5662 }
5663
5664 #[test]
5665 fn validate_call_as_load_operand_official_case() {
5666 let bytes =
5667 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-load-operand.wasm");
5668 let module = Module::decode(bytes).unwrap();
5669 module.validate().unwrap();
5670 }
5671
5672 #[test]
5673 fn validate_call_as_compare_right_official_case() {
5674 let bytes =
5675 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-compare-right.wasm",);
5676 let module = Module::decode(bytes).unwrap();
5677 module.validate().unwrap();
5678 }
5679
5680 #[test]
5681 fn validate_call_as_convert_operand_official_case() {
5682 let bytes =
5683 include_bytes!("../../../baedeker-testdata/spec/valid/call-as-convert-operand.wasm",);
5684 let module = Module::decode(bytes).unwrap();
5685 module.validate().unwrap();
5686 }
5687
5688 #[test]
5689 fn validate_unreachable_as_func_mid_official_case() {
5690 let bytes =
5691 include_bytes!("../../../baedeker-testdata/spec/valid/unreachable-as-func-mid.wasm");
5692 let module = Module::decode(bytes).unwrap();
5693 module.validate().unwrap();
5694 }
5695
5696 #[test]
5697 fn validate_unreachable_as_block_value_official_case() {
5698 let bytes = include_bytes!(
5699 "../../../baedeker-testdata/spec/valid/unreachable-as-block-value.wasm",
5700 );
5701 let module = Module::decode(bytes).unwrap();
5702 module.validate().unwrap();
5703 }
5704
5705 #[test]
5706 fn validate_unreachable_as_br_table_value_index_official_case() {
5707 let bytes = include_bytes!(
5708 "../../../baedeker-testdata/spec/valid/unreachable-as-br-table-value-index.wasm",
5709 );
5710 let module = Module::decode(bytes).unwrap();
5711 module.validate().unwrap();
5712 }
5713
5714 #[test]
5715 fn validate_unreachable_as_if_then_no_else_official_case() {
5716 let bytes = include_bytes!(
5717 "../../../baedeker-testdata/spec/valid/unreachable-as-if-then-no-else.wasm",
5718 );
5719 let module = Module::decode(bytes).unwrap();
5720 module.validate().unwrap();
5721 }
5722
5723 #[test]
5724 fn validate_unreachable_as_call_indirect_first_official_case() {
5725 let bytes = include_bytes!(
5726 "../../../baedeker-testdata/spec/valid/unreachable-as-call-indirect-first.wasm",
5727 );
5728 let module = Module::decode(bytes).unwrap();
5729 module.validate().unwrap();
5730 }
5731
5732 #[test]
5733 fn validate_unreachable_as_local_tee_value_official_case() {
5734 let bytes = include_bytes!(
5735 "../../../baedeker-testdata/spec/valid/unreachable-as-local-tee-value.wasm",
5736 );
5737 let module = Module::decode(bytes).unwrap();
5738 module.validate().unwrap();
5739 }
5740
5741 #[test]
5742 fn validate_unreachable_as_store_n_value_official_case() {
5743 let bytes = include_bytes!(
5744 "../../../baedeker-testdata/spec/valid/unreachable-as-storeN-value.wasm",
5745 );
5746 let module = Module::decode(bytes).unwrap();
5747 module.validate().unwrap();
5748 }
5749
5750 #[test]
5751 fn validate_unreachable_as_convert_operand_official_case() {
5752 let bytes = include_bytes!(
5753 "../../../baedeker-testdata/spec/valid/unreachable-as-convert-operand.wasm",
5754 );
5755 let module = Module::decode(bytes).unwrap();
5756 module.validate().unwrap();
5757 }
5758
5759 #[test]
5760 fn validate_call_indirect_as_select_last_official_case() {
5761 let bytes = include_bytes!(
5762 "../../../baedeker-testdata/spec/valid/call-indirect-as-select-last.wasm",
5763 );
5764 let module = Module::decode(bytes).unwrap();
5765 module.validate().unwrap();
5766 }
5767
5768 #[test]
5769 fn validate_call_indirect_as_br_if_first_official_case() {
5770 let bytes = include_bytes!(
5771 "../../../baedeker-testdata/spec/valid/call-indirect-as-br-if-first.wasm",
5772 );
5773 let module = Module::decode(bytes).unwrap();
5774 module.validate().unwrap();
5775 }
5776
5777 #[test]
5778 fn validate_call_indirect_as_store_last_official_case() {
5779 let bytes = include_bytes!(
5780 "../../../baedeker-testdata/spec/valid/call-indirect-as-store-last.wasm",
5781 );
5782 let module = Module::decode(bytes).unwrap();
5783 module.validate().unwrap();
5784 }
5785
5786 #[test]
5787 fn validate_call_indirect_as_memory_grow_value_official_case() {
5788 let bytes = include_bytes!(
5789 "../../../baedeker-testdata/spec/valid/call-indirect-as-memory-grow-value.wasm",
5790 );
5791 let module = Module::decode(bytes).unwrap();
5792 module.validate().unwrap();
5793 }
5794
5795 #[test]
5796 fn validate_call_indirect_as_local_tee_value_official_case() {
5797 let bytes = include_bytes!(
5798 "../../../baedeker-testdata/spec/valid/call-indirect-as-local-tee-value.wasm",
5799 );
5800 let module = Module::decode(bytes).unwrap();
5801 module.validate().unwrap();
5802 }
5803
5804 #[test]
5805 fn validate_call_indirect_as_load_operand_official_case() {
5806 let bytes = include_bytes!(
5807 "../../../baedeker-testdata/spec/valid/call-indirect-as-load-operand.wasm",
5808 );
5809 let module = Module::decode(bytes).unwrap();
5810 module.validate().unwrap();
5811 }
5812
5813 #[test]
5814 fn validate_call_indirect_as_compare_right_official_case() {
5815 let bytes = include_bytes!(
5816 "../../../baedeker-testdata/spec/valid/call-indirect-as-compare-right.wasm",
5817 );
5818 let module = Module::decode(bytes).unwrap();
5819 module.validate().unwrap();
5820 }
5821
5822 #[test]
5823 fn validate_call_indirect_as_convert_operand_official_case() {
5824 let bytes = include_bytes!(
5825 "../../../baedeker-testdata/spec/valid/call-indirect-as-convert-operand.wasm",
5826 );
5827 let module = Module::decode(bytes).unwrap();
5828 module.validate().unwrap();
5829 }
5830
5831 #[test]
5832 fn validate_block_as_select_cond_official_case() {
5833 let bytes =
5834 include_bytes!("../../../baedeker-testdata/spec/valid/block-as-select-cond.wasm");
5835 let module = Module::decode(bytes).unwrap();
5836 module.validate().unwrap();
5837 }
5838
5839 #[test]
5840 fn validate_block_as_load_address_official_case() {
5841 let bytes =
5842 include_bytes!("../../../baedeker-testdata/spec/valid/block-as-load-address.wasm");
5843 let module = Module::decode(bytes).unwrap();
5844 module.validate().unwrap();
5845 }
5846
5847 #[test]
5848 fn validate_if_as_call_indirect_last_official_case() {
5849 let bytes =
5850 include_bytes!("../../../baedeker-testdata/spec/valid/if-as-call-indirect-last.wasm",);
5851 let module = Module::decode(bytes).unwrap();
5852 module.validate().unwrap();
5853 }
5854
5855 #[test]
5856 fn validate_if_as_memory_grow_size_official_case() {
5857 let bytes =
5858 include_bytes!("../../../baedeker-testdata/spec/valid/if-as-memory-grow-size.wasm");
5859 let module = Module::decode(bytes).unwrap();
5860 module.validate().unwrap();
5861 }
5862
5863 #[test]
5864 fn validate_loop_as_local_tee_value_official_case() {
5865 let bytes =
5866 include_bytes!("../../../baedeker-testdata/spec/valid/loop-as-local-tee-value.wasm");
5867 let module = Module::decode(bytes).unwrap();
5868 module.validate().unwrap();
5869 }
5870
5871 #[test]
5872 fn validate_loop_as_memory_grow_size_official_case() {
5873 let bytes =
5874 include_bytes!("../../../baedeker-testdata/spec/valid/loop-as-memory-grow-size.wasm",);
5875 let module = Module::decode(bytes).unwrap();
5876 module.validate().unwrap();
5877 }
5878
5879 #[test]
5880 fn validate_return_as_call_value_official_case() {
5881 let bytes =
5882 include_bytes!("../../../baedeker-testdata/spec/valid/return-as-call-value.wasm");
5883 let module = Module::decode(bytes).unwrap();
5884 module.validate().unwrap();
5885 }
5886
5887 #[test]
5888 fn validate_return_as_br_value_official_case() {
5889 let bytes = include_bytes!("../../../baedeker-testdata/spec/valid/return-as-br-value.wasm");
5890 let module = Module::decode(bytes).unwrap();
5891 module.validate().unwrap();
5892 }
5893
5894 #[test]
5895 fn validate_br_as_br_if_value_cond_official_case() {
5896 let bytes =
5897 include_bytes!("../../../baedeker-testdata/spec/valid/br-as-br-if-value-cond.wasm");
5898 let module = Module::decode(bytes).unwrap();
5899 module.validate().unwrap();
5900 }
5901
5902 #[test]
5903 fn validate_br_as_select_all_official_case() {
5904 let bytes = include_bytes!("../../../baedeker-testdata/spec/valid/br-as-select-all.wasm");
5905 let module = Module::decode(bytes).unwrap();
5906 module.validate().unwrap();
5907 }
5908
5909 #[test]
5910 fn validate_br_as_call_indirect_all_official_case() {
5911 let bytes =
5912 include_bytes!("../../../baedeker-testdata/spec/valid/br-as-call-indirect-all.wasm",);
5913 let module = Module::decode(bytes).unwrap();
5914 module.validate().unwrap();
5915 }
5916
5917 #[test]
5918 fn validate_br_as_local_tee_value_official_case() {
5919 let bytes =
5920 include_bytes!("../../../baedeker-testdata/spec/valid/br-as-local-tee-value.wasm");
5921 let module = Module::decode(bytes).unwrap();
5922 module.validate().unwrap();
5923 }
5924
5925 #[test]
5926 fn validate_br_as_load_address_official_case() {
5927 let bytes = include_bytes!("../../../baedeker-testdata/spec/valid/br-as-load-address.wasm");
5928 let module = Module::decode(bytes).unwrap();
5929 module.validate().unwrap();
5930 }
5931
5932 #[test]
5933 fn validate_br_as_store_n_value_official_case() {
5934 let bytes = include_bytes!("../../../baedeker-testdata/spec/valid/br-as-storeN-value.wasm");
5935 let module = Module::decode(bytes).unwrap();
5936 module.validate().unwrap();
5937 }
5938
5939 #[test]
5940 fn validate_br_as_memory_grow_size_official_case() {
5941 let bytes =
5942 include_bytes!("../../../baedeker-testdata/spec/valid/br-as-memory-grow-size.wasm",);
5943 let module = Module::decode(bytes).unwrap();
5944 module.validate().unwrap();
5945 }
5946
5947 #[test]
5948 fn validate_br_if_as_br_if_value_cond_official_case() {
5949 let bytes =
5950 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-br-if-value-cond.wasm",);
5951 let module = Module::decode(bytes).unwrap();
5952 module.validate().unwrap();
5953 }
5954
5955 #[test]
5956 fn validate_br_if_as_select_cond_official_case() {
5957 let bytes =
5958 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-select-cond.wasm");
5959 let module = Module::decode(bytes).unwrap();
5960 module.validate().unwrap();
5961 }
5962
5963 #[test]
5964 fn validate_br_if_as_call_indirect_last_official_case() {
5965 let bytes = include_bytes!(
5966 "../../../baedeker-testdata/spec/valid/br-if-as-call-indirect-last.wasm",
5967 );
5968 let module = Module::decode(bytes).unwrap();
5969 module.validate().unwrap();
5970 }
5971
5972 #[test]
5973 fn validate_br_if_as_local_tee_value_official_case() {
5974 let bytes =
5975 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-local-tee-value.wasm",);
5976 let module = Module::decode(bytes).unwrap();
5977 module.validate().unwrap();
5978 }
5979
5980 #[test]
5981 fn validate_br_if_as_load_address_official_case() {
5982 let bytes =
5983 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-load-address.wasm");
5984 let module = Module::decode(bytes).unwrap();
5985 module.validate().unwrap();
5986 }
5987
5988 #[test]
5989 fn validate_br_if_as_store_n_value_official_case() {
5990 let bytes =
5991 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-storeN-value.wasm");
5992 let module = Module::decode(bytes).unwrap();
5993 module.validate().unwrap();
5994 }
5995
5996 #[test]
5997 fn validate_br_if_as_memory_grow_size_official_case() {
5998 let bytes =
5999 include_bytes!("../../../baedeker-testdata/spec/valid/br-if-as-memory-grow-size.wasm",);
6000 let module = Module::decode(bytes).unwrap();
6001 module.validate().unwrap();
6002 }
6003
6004 #[test]
6005 fn validate_br_table_with_matching_label_types() {
6006 let bytes = [
6007 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
6008 0x03, 0x02, 0x01, 0x00, 0x0A, 0x10, 0x01, 0x0E, 0x00, 0x02, 0x7F, 0x41, 0x01, 0x41,
6009 0x00, 0x0E, 0x01, 0x00, 0x00, 0x0B, 0x1A, 0x0B,
6010 ];
6011 let module = Module::decode(&bytes).unwrap();
6012 module.validate().unwrap();
6013 }
6014
6015 #[test]
6016 fn validate_br_table_type_f64_value_official_case() {
6017 let bytes =
6018 include_bytes!("../../../baedeker-testdata/spec/valid/br-table-type-f64-value.wasm");
6019 let module = Module::decode(bytes).unwrap();
6020 module.validate().unwrap();
6021 }
6022
6023 #[test]
6024 fn validate_br_table_as_br_if_value_cond_official_case() {
6025 let bytes = include_bytes!(
6026 "../../../baedeker-testdata/spec/valid/br-table-as-br-if-value-cond.wasm",
6027 );
6028 let module = Module::decode(bytes).unwrap();
6029 module.validate().unwrap();
6030 }
6031
6032 #[test]
6033 fn validate_br_table_as_call_indirect_func_official_case() {
6034 let bytes = include_bytes!(
6035 "../../../baedeker-testdata/spec/valid/br-table-as-call-indirect-func.wasm",
6036 );
6037 let module = Module::decode(bytes).unwrap();
6038 module.validate().unwrap();
6039 }
6040
6041 #[test]
6042 fn validate_br_table_as_local_set_value_official_case() {
6043 let bytes = include_bytes!(
6044 "../../../baedeker-testdata/spec/valid/br-table-as-local-set-value.wasm",
6045 );
6046 let module = Module::decode(bytes).unwrap();
6047 module.validate().unwrap();
6048 }
6049
6050 #[test]
6051 fn validate_br_table_as_load_address_official_case() {
6052 let bytes =
6053 include_bytes!("../../../baedeker-testdata/spec/valid/br-table-as-load-address.wasm");
6054 let module = Module::decode(bytes).unwrap();
6055 module.validate().unwrap();
6056 }
6057
6058 #[test]
6059 fn validate_br_table_as_store_value_official_case() {
6060 let bytes =
6061 include_bytes!("../../../baedeker-testdata/spec/valid/br-table-as-store-value.wasm");
6062 let module = Module::decode(bytes).unwrap();
6063 module.validate().unwrap();
6064 }
6065
6066 #[test]
6067 fn validate_br_table_as_compare_left_official_case() {
6068 let bytes =
6069 include_bytes!("../../../baedeker-testdata/spec/valid/br-table-as-compare-left.wasm");
6070 let module = Module::decode(bytes).unwrap();
6071 module.validate().unwrap();
6072 }
6073
6074 #[test]
6075 fn validate_br_table_as_memory_grow_size_official_case() {
6076 let bytes = include_bytes!(
6077 "../../../baedeker-testdata/spec/valid/br-table-as-memory-grow-size.wasm",
6078 );
6079 let module = Module::decode(bytes).unwrap();
6080 module.validate().unwrap();
6081 }
6082
6083 #[test]
6084 fn validate_official_labels_block_case() {
6085 let bytes =
6086 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-block.wasm",);
6087 let module = Module::decode(bytes).unwrap();
6088 module.validate().unwrap();
6089 }
6090
6091 #[test]
6092 fn validate_official_labels_loop1_case() {
6093 let bytes =
6094 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop1.wasm",);
6095 let module = Module::decode(bytes).unwrap();
6096 module.validate().unwrap();
6097 }
6098
6099 #[test]
6100 fn validate_official_labels_loop2_case() {
6101 let bytes =
6102 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop2.wasm",);
6103 let module = Module::decode(bytes).unwrap();
6104 module.validate().unwrap();
6105 }
6106
6107 #[test]
6108 fn validate_official_labels_loop3_case() {
6109 let bytes =
6110 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop3.wasm",);
6111 let module = Module::decode(bytes).unwrap();
6112 module.validate().unwrap();
6113 }
6114
6115 #[test]
6116 fn validate_official_labels_loop4_case() {
6117 let bytes =
6118 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop4.wasm",);
6119 let module = Module::decode(bytes).unwrap();
6120 module.validate().unwrap();
6121 }
6122
6123 #[test]
6124 fn validate_official_labels_if_case() {
6125 let bytes =
6126 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-if.wasm",);
6127 let module = Module::decode(bytes).unwrap();
6128 module.validate().unwrap();
6129 }
6130
6131 #[test]
6132 fn validate_official_labels_if2_case() {
6133 let bytes =
6134 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-if2.wasm",);
6135 let module = Module::decode(bytes).unwrap();
6136 module.validate().unwrap();
6137 }
6138
6139 #[test]
6140 fn validate_official_labels_return_case() {
6141 let bytes =
6142 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-return.wasm",);
6143 let module = Module::decode(bytes).unwrap();
6144 module.validate().unwrap();
6145 }
6146
6147 #[test]
6148 fn validate_official_labels_br_if0_case() {
6149 let bytes =
6150 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-br-if0.wasm",);
6151 let module = Module::decode(bytes).unwrap();
6152 module.validate().unwrap();
6153 }
6154
6155 #[test]
6156 fn validate_official_labels_br_case() {
6157 let bytes =
6158 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-br.wasm",);
6159 let module = Module::decode(bytes).unwrap();
6160 module.validate().unwrap();
6161 }
6162
6163 #[test]
6164 fn validate_official_switch_stmt_case() {
6165 let bytes =
6166 include_bytes!("../../../baedeker-testdata/spec/valid/official-switch-stmt.wasm",);
6167 let module = Module::decode(bytes).unwrap();
6168 module.validate().unwrap();
6169 }
6170
6171 #[test]
6172 fn validate_official_switch_expr_case() {
6173 let bytes =
6174 include_bytes!("../../../baedeker-testdata/spec/valid/official-switch-expr.wasm",);
6175 let module = Module::decode(bytes).unwrap();
6176 module.validate().unwrap();
6177 }
6178
6179 #[test]
6180 fn validate_official_switch_arg_case() {
6181 let bytes =
6182 include_bytes!("../../../baedeker-testdata/spec/valid/official-switch-arg.wasm",);
6183 let module = Module::decode(bytes).unwrap();
6184 module.validate().unwrap();
6185 }
6186
6187 #[test]
6188 fn validate_official_ref_typed_syntax_case() {
6189 let bytes =
6190 include_bytes!("../../../baedeker-testdata/spec/valid/official-ref-typed-syntax.wasm",);
6191 let module = Module::decode(bytes).unwrap();
6192 module.validate().unwrap();
6193 }
6194
6195 #[test]
6196 fn validate_official_labels_loop5_case() {
6197 let bytes =
6198 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop5.wasm",);
6199 let module = Module::decode(bytes).unwrap();
6200 module.validate().unwrap();
6201 }
6202
6203 #[test]
6204 fn validate_official_labels_loop6_case() {
6205 let bytes =
6206 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-loop6.wasm",);
6207 let module = Module::decode(bytes).unwrap();
6208 module.validate().unwrap();
6209 }
6210
6211 #[test]
6212 fn validate_official_labels_br_if1_case() {
6213 let bytes =
6214 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-br-if1.wasm",);
6215 let module = Module::decode(bytes).unwrap();
6216 module.validate().unwrap();
6217 }
6218
6219 #[test]
6220 fn validate_official_labels_br_if2_case() {
6221 let bytes =
6222 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-br-if2.wasm",);
6223 let module = Module::decode(bytes).unwrap();
6224 module.validate().unwrap();
6225 }
6226
6227 #[test]
6228 fn validate_official_labels_br_if3_case() {
6229 let bytes =
6230 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-br-if3.wasm",);
6231 let module = Module::decode(bytes).unwrap();
6232 module.validate().unwrap();
6233 }
6234
6235 #[test]
6236 fn validate_official_labels_shadowing_case() {
6237 let bytes =
6238 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-shadowing.wasm",);
6239 let module = Module::decode(bytes).unwrap();
6240 module.validate().unwrap();
6241 }
6242
6243 #[test]
6244 fn validate_official_labels_redefinition_case() {
6245 let bytes = include_bytes!(
6246 "../../../baedeker-testdata/spec/valid/official-labels-redefinition.wasm",
6247 );
6248 let module = Module::decode(bytes).unwrap();
6249 module.validate().unwrap();
6250 }
6251
6252 #[test]
6253 fn validate_official_labels_switch_case() {
6254 let bytes =
6255 include_bytes!("../../../baedeker-testdata/spec/valid/official-labels-switch.wasm",);
6256 let module = Module::decode(bytes).unwrap();
6257 module.validate().unwrap();
6258 }
6259
6260 #[test]
6261 fn validate_official_switch_corner_case() {
6262 let bytes =
6263 include_bytes!("../../../baedeker-testdata/spec/valid/official-switch-corner.wasm",);
6264 let module = Module::decode(bytes).unwrap();
6265 module.validate().unwrap();
6266 }
6267
6268 #[test]
6269 fn validate_typed_br_if_with_equivalent_signature() {
6270 let bytes = [
6271 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7f,
6272 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
6273 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x13, 0x02,
6274 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x02, 0x63, 0x01, 0xd2, 0x00, 0x20, 0x00,
6275 0x0d, 0x00, 0x0b, 0x0b,
6276 ];
6277 let module = Module::decode(&bytes).unwrap();
6278 module.validate().unwrap();
6279 }
6280
6281 #[test]
6282 fn reject_typed_br_if_with_wrong_concrete_type() {
6283 let bytes = [
6284 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7e,
6285 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
6286 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x13, 0x02,
6287 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x02, 0x63, 0x01, 0xd2, 0x00, 0x20, 0x00,
6288 0x0d, 0x00, 0x0b, 0x0b,
6289 ];
6290 let module = Module::decode(&bytes).unwrap();
6291 let err = module.validate().unwrap_err();
6292 assert_eq!(err.offset, ByteOffset(56));
6293 assert!(matches!(
6294 err.kind,
6295 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6296 if label == crate::types::LabelIdx(0)
6297 && expected == vec![ValType::Ref(RefType::Typed {
6298 nullable: true,
6299 heap: crate::types::HeapType::Type(TypeIdx(1)),
6300 })]
6301 && found == vec![ValType::Ref(RefType::Typed {
6302 nullable: false,
6303 heap: crate::types::HeapType::Type(TypeIdx(0)),
6304 })]
6305 ));
6306 }
6307
6308 #[test]
6309 fn validate_typed_select_to_br_if_nullable_official_case() {
6310 let bytes = include_bytes!(
6311 "../../../baedeker-testdata/spec/valid/typed-select-to-br-if-nullable.wasm",
6312 );
6313 let module = Module::decode(bytes).unwrap();
6314 module.validate().unwrap();
6315 }
6316
6317 #[test]
6318 fn reject_typed_select_to_br_if_nullability_mismatch() {
6319 let bytes = include_bytes!(
6320 "../../../baedeker-testdata/spec/invalid-validate/typed-select-to-br-if-nullability-mismatch.wasm",
6321 );
6322 let module = Module::decode(bytes).unwrap();
6323 let err = module.validate().unwrap_err();
6324 assert_eq!(err.offset, ByteOffset(60));
6325 assert!(matches!(
6326 err.kind,
6327 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6328 if label == crate::types::LabelIdx(0)
6329 && expected == vec![ValType::Ref(RefType::Typed {
6330 nullable: false,
6331 heap: crate::types::HeapType::Type(TypeIdx(0)),
6332 })]
6333 && found == vec![ValType::Ref(RefType::Typed {
6334 nullable: true,
6335 heap: crate::types::HeapType::Type(TypeIdx(0)),
6336 })]
6337 ));
6338 }
6339
6340 #[test]
6341 fn validate_typed_table_init_to_br_if_nullable_official_case() {
6342 let bytes = include_bytes!(
6343 "../../../baedeker-testdata/spec/valid/typed-table-init-to-br-if-nullable.wasm",
6344 );
6345 let module = Module::decode(bytes).unwrap();
6346 module.validate().unwrap();
6347 }
6348
6349 #[test]
6350 fn reject_typed_table_init_to_br_if_nullability_mismatch() {
6351 let bytes = include_bytes!(
6352 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-to-br-if-nullability-mismatch.wasm",
6353 );
6354 let module = Module::decode(bytes).unwrap();
6355 let err = module.validate().unwrap_err();
6356 assert_eq!(err.offset, ByteOffset(89));
6357 assert!(matches!(
6358 err.kind,
6359 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6360 if label == crate::types::LabelIdx(0)
6361 && expected == vec![ValType::Ref(RefType::Typed {
6362 nullable: false,
6363 heap: crate::types::HeapType::Type(TypeIdx(0)),
6364 })]
6365 && found == vec![ValType::Ref(RefType::Typed {
6366 nullable: true,
6367 heap: crate::types::HeapType::Type(TypeIdx(0)),
6368 })]
6369 ));
6370 }
6371
6372 #[test]
6373 fn validate_typed_table_init_shared_source_to_br_if_nullable_official_case() {
6374 let bytes = include_bytes!(
6375 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-br-if-nullable.wasm",
6376 );
6377 let module = Module::decode(bytes).unwrap();
6378 module.validate().unwrap();
6379 }
6380
6381 #[test]
6382 fn reject_typed_table_init_shared_source_to_br_if_nullability_mismatch() {
6383 let bytes = include_bytes!(
6384 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-br-if-nullability-mismatch.wasm",
6385 );
6386 let module = Module::decode(bytes).unwrap();
6387 let err = module.validate().unwrap_err();
6388 assert_eq!(err.offset, ByteOffset(100));
6389 assert!(matches!(
6390 err.kind,
6391 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6392 if label == crate::types::LabelIdx(0)
6393 && expected == vec![ValType::Ref(RefType::Typed {
6394 nullable: false,
6395 heap: crate::types::HeapType::Type(TypeIdx(1)),
6396 })]
6397 && found == vec![ValType::Ref(RefType::Typed {
6398 nullable: true,
6399 heap: crate::types::HeapType::Type(TypeIdx(1)),
6400 })]
6401 ));
6402 }
6403
6404 #[test]
6405 fn validate_typed_br_to_loop_param_with_equivalent_signature() {
6406 let bytes = [
6407 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7f,
6408 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x00, 0x60, 0x01,
6409 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x01, 0x02, 0x07, 0x05, 0x01, 0x01,
6410 0x66, 0x00, 0x00, 0x0a, 0x17, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x10, 0x00, 0x02,
6411 0x63, 0x00, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x0c, 0x00, 0x0b, 0x0b, 0x0b,
6412 ];
6413 let module = Module::decode(&bytes).unwrap();
6414 module.validate().unwrap();
6415 }
6416
6417 #[test]
6418 fn reject_typed_br_to_loop_param_with_wrong_concrete_type() {
6419 let bytes = [
6420 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7e,
6421 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x00, 0x60, 0x01,
6422 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x01, 0x02, 0x07, 0x05, 0x01, 0x01,
6423 0x66, 0x00, 0x00, 0x0a, 0x17, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x10, 0x00, 0x02,
6424 0x63, 0x00, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x0c, 0x00, 0x0b, 0x0b, 0x0b,
6425 ];
6426 let module = Module::decode(&bytes).unwrap();
6427 let err = module.validate().unwrap_err();
6428 assert_eq!(err.offset, ByteOffset(65));
6429 assert!(matches!(
6430 err.kind,
6431 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6432 if label == crate::types::LabelIdx(0)
6433 && expected == vec![ValType::Ref(RefType::Typed {
6434 nullable: true,
6435 heap: crate::types::HeapType::Type(TypeIdx(0)),
6436 })]
6437 && found == vec![ValType::Ref(RefType::Typed {
6438 nullable: false,
6439 heap: crate::types::HeapType::Type(TypeIdx(1)),
6440 })]
6441 ));
6442 }
6443
6444 #[test]
6445 fn validate_typed_br_to_loop_param_nullable_official_case() {
6446 let bytes = include_bytes!(
6447 "../../../baedeker-testdata/spec/valid/typed-br-to-loop-param-nullable.wasm",
6448 );
6449 let module = Module::decode(bytes).unwrap();
6450 module.validate().unwrap();
6451 }
6452
6453 #[test]
6454 fn reject_typed_br_to_loop_param_nullability_mismatch() {
6455 let bytes = include_bytes!(
6456 "../../../baedeker-testdata/spec/invalid-validate/typed-br-to-loop-param-nullability-mismatch.wasm",
6457 );
6458 let module = Module::decode(bytes).unwrap();
6459 let err = module.validate().unwrap_err();
6460 assert_eq!(err.offset, ByteOffset(69));
6461 assert!(matches!(
6462 err.kind,
6463 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6464 if label == crate::types::LabelIdx(0)
6465 && expected == vec![ValType::Ref(RefType::Typed {
6466 nullable: false,
6467 heap: crate::types::HeapType::Type(TypeIdx(0)),
6468 })]
6469 && found == vec![ValType::Ref(RefType::Typed {
6470 nullable: true,
6471 heap: crate::types::HeapType::Type(TypeIdx(0)),
6472 })]
6473 ));
6474 }
6475
6476 #[test]
6477 fn validate_typed_br_if_to_loop_param_with_equivalent_signature() {
6478 let bytes = [
6479 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7f,
6480 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x00, 0x60, 0x01,
6481 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x01, 0x02, 0x07, 0x05, 0x01, 0x01,
6482 0x66, 0x00, 0x00, 0x0a, 0x19, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x12, 0x00, 0x02,
6483 0x63, 0x00, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x41, 0x01, 0x0d, 0x00, 0x0b,
6484 0x0b, 0x0b,
6485 ];
6486 let module = Module::decode(&bytes).unwrap();
6487 module.validate().unwrap();
6488 }
6489
6490 #[test]
6491 fn reject_typed_br_if_to_loop_param_with_wrong_concrete_type() {
6492 let bytes = [
6493 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7e,
6494 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x00, 0x60, 0x01,
6495 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x01, 0x02, 0x07, 0x05, 0x01, 0x01,
6496 0x66, 0x00, 0x00, 0x0a, 0x19, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x12, 0x00, 0x02,
6497 0x63, 0x00, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x41, 0x01, 0x0d, 0x00, 0x0b,
6498 0x0b, 0x0b,
6499 ];
6500 let module = Module::decode(&bytes).unwrap();
6501 let err = module.validate().unwrap_err();
6502 assert_eq!(err.offset, ByteOffset(67));
6503 assert!(matches!(
6504 err.kind,
6505 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6506 if label == crate::types::LabelIdx(0)
6507 && expected == vec![ValType::Ref(RefType::Typed {
6508 nullable: true,
6509 heap: crate::types::HeapType::Type(TypeIdx(0)),
6510 })]
6511 && found == vec![ValType::Ref(RefType::Typed {
6512 nullable: false,
6513 heap: crate::types::HeapType::Type(TypeIdx(1)),
6514 })]
6515 ));
6516 }
6517
6518 #[test]
6519 fn validate_typed_br_table_with_equivalent_signature() {
6520 let bytes = [
6521 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
6522 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
6523 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x15, 0x02, 0x04,
6524 0x00, 0x20, 0x00, 0x0b, 0x0e, 0x00, 0x02, 0x63, 0x01, 0xd2, 0x00, 0x41, 0x00, 0x0e,
6525 0x01, 0x00, 0x00, 0x0b, 0x0b,
6526 ];
6527 let module = Module::decode(&bytes).unwrap();
6528 module.validate().unwrap();
6529 }
6530
6531 #[test]
6532 fn reject_typed_br_table_with_wrong_concrete_type() {
6533 let bytes = [
6534 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7e,
6535 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
6536 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x15, 0x02, 0x04,
6537 0x00, 0x20, 0x00, 0x0b, 0x0e, 0x00, 0x02, 0x63, 0x01, 0xd2, 0x00, 0x41, 0x00, 0x0e,
6538 0x01, 0x00, 0x00, 0x0b, 0x0b,
6539 ];
6540 let module = Module::decode(&bytes).unwrap();
6541 let err = module.validate().unwrap_err();
6542 assert_eq!(err.offset, ByteOffset(55));
6543 assert!(matches!(
6544 err.kind,
6545 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6546 if label == crate::types::LabelIdx(0)
6547 && expected == vec![ValType::Ref(RefType::Typed {
6548 nullable: true,
6549 heap: crate::types::HeapType::Type(TypeIdx(1)),
6550 })]
6551 && found == vec![ValType::Ref(RefType::Typed {
6552 nullable: false,
6553 heap: crate::types::HeapType::Type(TypeIdx(0)),
6554 })]
6555 ));
6556 }
6557
6558 #[test]
6559 fn validate_typed_select_to_br_table_nullable_official_case() {
6560 let bytes = include_bytes!(
6561 "../../../baedeker-testdata/spec/valid/typed-select-to-br-table-nullable.wasm",
6562 );
6563 let module = Module::decode(bytes).unwrap();
6564 module.validate().unwrap();
6565 }
6566
6567 #[test]
6568 fn reject_typed_select_to_br_table_nullability_mismatch() {
6569 let bytes = include_bytes!(
6570 "../../../baedeker-testdata/spec/invalid-validate/typed-select-to-br-table-nullability-mismatch.wasm",
6571 );
6572 let module = Module::decode(bytes).unwrap();
6573 let err = module.validate().unwrap_err();
6574 assert_eq!(err.offset, ByteOffset(59));
6575 assert!(matches!(
6576 err.kind,
6577 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6578 if label == crate::types::LabelIdx(0)
6579 && expected == vec![ValType::Ref(RefType::Typed {
6580 nullable: false,
6581 heap: crate::types::HeapType::Type(TypeIdx(0)),
6582 })]
6583 && found == vec![ValType::Ref(RefType::Typed {
6584 nullable: true,
6585 heap: crate::types::HeapType::Type(TypeIdx(0)),
6586 })]
6587 ));
6588 }
6589
6590 #[test]
6591 fn validate_typed_table_init_to_br_table_nullable_official_case() {
6592 let bytes = include_bytes!(
6593 "../../../baedeker-testdata/spec/valid/typed-table-init-to-br-table-nullable.wasm",
6594 );
6595 let module = Module::decode(bytes).unwrap();
6596 module.validate().unwrap();
6597 }
6598
6599 #[test]
6600 fn reject_typed_table_init_to_br_table_nullability_mismatch() {
6601 let bytes = include_bytes!(
6602 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-to-br-table-nullability-mismatch.wasm",
6603 );
6604 let module = Module::decode(bytes).unwrap();
6605 let err = module.validate().unwrap_err();
6606 assert_eq!(err.offset, ByteOffset(88));
6607 assert!(matches!(
6608 err.kind,
6609 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6610 if label == crate::types::LabelIdx(0)
6611 && expected == vec![ValType::Ref(RefType::Typed {
6612 nullable: false,
6613 heap: crate::types::HeapType::Type(TypeIdx(0)),
6614 })]
6615 && found == vec![ValType::Ref(RefType::Typed {
6616 nullable: true,
6617 heap: crate::types::HeapType::Type(TypeIdx(0)),
6618 })]
6619 ));
6620 }
6621
6622 #[test]
6623 fn validate_typed_table_init_shared_source_to_br_table_nullable_official_case() {
6624 let bytes = include_bytes!(
6625 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-br-table-nullable.wasm",
6626 );
6627 let module = Module::decode(bytes).unwrap();
6628 module.validate().unwrap();
6629 }
6630
6631 #[test]
6632 fn reject_typed_table_init_shared_source_to_br_table_nullability_mismatch() {
6633 let bytes = include_bytes!(
6634 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-br-table-nullability-mismatch.wasm",
6635 );
6636 let module = Module::decode(bytes).unwrap();
6637 let err = module.validate().unwrap_err();
6638 assert_eq!(err.offset, ByteOffset(99));
6639 assert!(matches!(
6640 err.kind,
6641 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6642 if label == crate::types::LabelIdx(0)
6643 && expected == vec![ValType::Ref(RefType::Typed {
6644 nullable: false,
6645 heap: crate::types::HeapType::Type(TypeIdx(1)),
6646 })]
6647 && found == vec![ValType::Ref(RefType::Typed {
6648 nullable: true,
6649 heap: crate::types::HeapType::Type(TypeIdx(1)),
6650 })]
6651 ));
6652 }
6653
6654 #[test]
6658 fn validate_typed_br_table_nullability_targets_join() {
6659 let bytes = include_bytes!(
6660 "../../../baedeker-testdata/spec/valid/typed-br-table-nullability-targets-join.wasm",
6661 );
6662 let module = Module::decode(bytes).unwrap();
6663 module.validate().unwrap();
6664 }
6665
6666 #[test]
6667 fn validate_typed_select() {
6668 let bytes = [
6669 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
6670 0x7E, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0D, 0x01, 0x0B, 0x00, 0x42, 0x01, 0x42, 0x02,
6671 0x41, 0x00, 0x1C, 0x01, 0x7E, 0x0B,
6672 ];
6673 let module = Module::decode(&bytes).unwrap();
6674 module.validate().unwrap();
6675 }
6676
6677 #[test]
6678 fn validate_select_as_br_table_last_official_case() {
6679 let bytes =
6680 include_bytes!("../../../baedeker-testdata/spec/valid/select-as-br-table-last.wasm");
6681 let module = Module::decode(bytes).unwrap();
6682 module.validate().unwrap();
6683 }
6684
6685 #[test]
6686 fn validate_select_as_call_indirect_last_official_case() {
6687 let bytes = include_bytes!(
6688 "../../../baedeker-testdata/spec/valid/select-as-call-indirect-last.wasm",
6689 );
6690 let module = Module::decode(bytes).unwrap();
6691 module.validate().unwrap();
6692 }
6693
6694 #[test]
6695 fn validate_select_as_memory_grow_value_official_case() {
6696 let bytes = include_bytes!(
6697 "../../../baedeker-testdata/spec/valid/select-as-memory-grow-value.wasm",
6698 );
6699 let module = Module::decode(bytes).unwrap();
6700 module.validate().unwrap();
6701 }
6702
6703 #[test]
6704 fn validate_select_as_global_set_value_official_case() {
6705 let bytes = include_bytes!(
6706 "../../../baedeker-testdata/spec/valid/select-as-global-set-value.wasm",
6707 );
6708 let module = Module::decode(bytes).unwrap();
6709 module.validate().unwrap();
6710 }
6711
6712 #[test]
6713 fn validate_select_as_convert_operand_official_case() {
6714 let bytes =
6715 include_bytes!("../../../baedeker-testdata/spec/valid/select-as-convert-operand.wasm",);
6716 let module = Module::decode(bytes).unwrap();
6717 module.validate().unwrap();
6718 }
6719
6720 #[test]
6721 fn validate_select_as_if_condition_official_case() {
6722 let bytes =
6723 include_bytes!("../../../baedeker-testdata/spec/valid/select-as-if-condition.wasm");
6724 let module = Module::decode(bytes).unwrap();
6725 module.validate().unwrap();
6726 }
6727
6728 #[test]
6729 fn validate_typed_select_with_equivalent_concrete_type() {
6730 let bytes = [
6731 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7F,
6732 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x63, 0x01, 0x03,
6733 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x13, 0x02,
6734 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00, 0xD2, 0x00, 0xD0, 0x01, 0x20, 0x00, 0x1C,
6735 0x01, 0x63, 0x01, 0x0B,
6736 ];
6737 let module = Module::decode(&bytes).unwrap();
6738 module.validate().unwrap();
6739 }
6740
6741 #[test]
6742 fn reject_typed_select_wrong_operand_types() {
6743 let bytes = [
6744 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
6745 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0E, 0x01, 0x0C, 0x00, 0x41, 0x01, 0x41, 0x02, 0x41,
6746 0x00, 0x1C, 0x01, 0x7E, 0x1A, 0x0B,
6747 ];
6748 let module = Module::decode(&bytes).unwrap();
6749 let err = module.validate().unwrap_err();
6750 assert_eq!(err.offset, ByteOffset(29));
6751 assert!(matches!(
6752 err.kind,
6753 ValidationErrorKind::SelectOperandTypeMismatch { expected, found }
6754 if expected == ValType::Num(crate::types::NumType::I64)
6755 && found == vec![
6756 ValType::Num(crate::types::NumType::I32),
6757 ValType::Num(crate::types::NumType::I32),
6758 ]
6759 ));
6760 }
6761
6762 #[test]
6763 fn reject_typed_select_with_invalid_result_arity() {
6764 let bytes = [
6765 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
6766 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0D, 0x01, 0x0B, 0x00, 0x41, 0x01, 0x41, 0x02, 0x41,
6767 0x00, 0x1C, 0x00, 0x1A, 0x0B,
6768 ];
6769 let module = Module::decode(&bytes).unwrap();
6770 let err = module.validate().unwrap_err();
6771 assert_eq!(err.offset, ByteOffset(29));
6772 assert!(matches!(
6773 err.kind,
6774 ValidationErrorKind::InvalidSelectResultArity { found: 0 }
6775 ));
6776 }
6777
6778 #[test]
6779 fn reject_typed_select_with_wrong_concrete_type() {
6780 let bytes = [
6781 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7F,
6782 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x60, 0x01, 0x7F, 0x01, 0x63, 0x01, 0x03,
6783 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x13, 0x02,
6784 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00, 0xD2, 0x00, 0xD0, 0x01, 0x20, 0x00, 0x1C,
6785 0x01, 0x63, 0x01, 0x0B,
6786 ];
6787 let module = Module::decode(&bytes).unwrap();
6788 let err = module.validate().unwrap_err();
6789 assert_eq!(err.offset, ByteOffset(55));
6790 assert!(matches!(
6791 err.kind,
6792 ValidationErrorKind::SelectOperandTypeMismatch { expected, found }
6793 if expected == ValType::Ref(RefType::Typed {
6794 nullable: true,
6795 heap: crate::types::HeapType::Type(TypeIdx(1)),
6796 }) && found == vec![
6797 ValType::Ref(RefType::Typed {
6798 nullable: false,
6799 heap: crate::types::HeapType::Type(TypeIdx(0)),
6800 }),
6801 ValType::Ref(RefType::Typed {
6802 nullable: true,
6803 heap: crate::types::HeapType::Type(TypeIdx(1)),
6804 }),
6805 ]
6806 ));
6807 }
6808
6809 #[test]
6810 fn reject_typed_select_nullability_mismatch() {
6811 let bytes = include_bytes!(
6812 "../../../baedeker-testdata/spec/invalid-validate/typed-select-nullability-mismatch.wasm",
6813 );
6814 let module = Module::decode(bytes).unwrap();
6815 let err = module.validate().unwrap_err();
6816 assert_eq!(err.offset, ByteOffset(50));
6817 assert!(matches!(
6818 err.kind,
6819 ValidationErrorKind::SelectOperandTypeMismatch { expected, found }
6820 if expected == ValType::Ref(RefType::Typed {
6821 nullable: false,
6822 heap: crate::types::HeapType::Type(TypeIdx(0)),
6823 }) && found == vec![
6824 ValType::Ref(RefType::Typed {
6825 nullable: false,
6826 heap: crate::types::HeapType::Type(TypeIdx(0)),
6827 }),
6828 ValType::Ref(RefType::Typed {
6829 nullable: true,
6830 heap: crate::types::HeapType::Type(TypeIdx(0)),
6831 }),
6832 ]
6833 ));
6834 }
6835
6836 #[test]
6837 fn reject_typed_select_function_result_wrong_concrete_type() {
6838 let bytes = include_bytes!(
6839 "../../../baedeker-testdata/spec/invalid-validate/typed-select-function-result-wrong-concrete-type.wasm",
6840 );
6841 let module = Module::decode(bytes).unwrap();
6842 let err = module.validate().unwrap_err();
6843 assert_eq!(err.offset, ByteOffset(59));
6844 assert!(matches!(
6845 err.kind,
6846 ValidationErrorKind::FunctionResultTypeMismatch {
6847 expected,
6848 found,
6849 ..
6850 } if expected == vec![ValType::Ref(RefType::Typed {
6851 nullable: true,
6852 heap: crate::types::HeapType::Type(TypeIdx(1)),
6853 })] && found == vec![ValType::Ref(RefType::Typed {
6854 nullable: true,
6855 heap: crate::types::HeapType::Type(TypeIdx(0)),
6856 })]
6857 ));
6858 }
6859
6860 #[test]
6861 fn reject_typed_select_block_result_wrong_concrete_type() {
6862 let bytes = include_bytes!(
6863 "../../../baedeker-testdata/spec/invalid-validate/typed-select-block-result-wrong-concrete-type.wasm",
6864 );
6865 let module = Module::decode(bytes).unwrap();
6866 let err = module.validate().unwrap_err();
6867 assert_eq!(err.offset, ByteOffset(62));
6868 assert!(matches!(
6869 err.kind,
6870 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
6871 if expected == vec![ValType::Ref(RefType::Typed {
6872 nullable: true,
6873 heap: crate::types::HeapType::Type(TypeIdx(1)),
6874 })] && found == vec![ValType::Ref(RefType::Typed {
6875 nullable: true,
6876 heap: crate::types::HeapType::Type(TypeIdx(0)),
6877 })]
6878 ));
6879 }
6880
6881 #[test]
6882 fn reject_typed_select_if_result_wrong_concrete_type() {
6883 let bytes = include_bytes!(
6884 "../../../baedeker-testdata/spec/invalid-validate/typed-select-if-result-wrong-concrete-type.wasm",
6885 );
6886 let module = Module::decode(bytes).unwrap();
6887 let err = module.validate().unwrap_err();
6888 assert_eq!(err.offset, ByteOffset(64));
6889 assert!(matches!(
6890 err.kind,
6891 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
6892 if expected == vec![ValType::Ref(RefType::Typed {
6893 nullable: true,
6894 heap: crate::types::HeapType::Type(TypeIdx(1)),
6895 })] && found == vec![ValType::Ref(RefType::Typed {
6896 nullable: true,
6897 heap: crate::types::HeapType::Type(TypeIdx(0)),
6898 })]
6899 ));
6900 }
6901
6902 #[test]
6903 fn reject_typed_select_function_result_nullability_mismatch() {
6904 let bytes = include_bytes!(
6905 "../../../baedeker-testdata/spec/invalid-validate/typed-select-function-result-nullability-mismatch.wasm",
6906 );
6907 let module = Module::decode(bytes).unwrap();
6908 let err = module.validate().unwrap_err();
6909 assert_eq!(err.offset, ByteOffset(54));
6910 assert!(matches!(
6911 err.kind,
6912 ValidationErrorKind::FunctionResultTypeMismatch {
6913 expected,
6914 found,
6915 ..
6916 } if expected == vec![ValType::Ref(RefType::Typed {
6917 nullable: false,
6918 heap: crate::types::HeapType::Type(TypeIdx(0)),
6919 })] && found == vec![ValType::Ref(RefType::Typed {
6920 nullable: true,
6921 heap: crate::types::HeapType::Type(TypeIdx(0)),
6922 })]
6923 ));
6924 }
6925
6926 #[test]
6927 fn reject_br_table_with_inconsistent_target_types() {
6928 let bytes = [
6929 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
6930 0x03, 0x02, 0x01, 0x00, 0x0A, 0x10, 0x01, 0x0E, 0x00, 0x02, 0x7F, 0x02, 0x7E, 0x41,
6931 0x00, 0x0E, 0x01, 0x00, 0x01, 0x0B, 0x0B, 0x0B,
6932 ];
6933 let module = Module::decode(&bytes).unwrap();
6934 let err = module.validate().unwrap_err();
6935 assert_eq!(err.offset, ByteOffset(29));
6936 assert!(matches!(
6939 err.kind,
6940 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6941 if label == crate::types::LabelIdx(0)
6942 && expected == vec![ValType::Num(crate::types::NumType::I64)]
6943 && found.is_empty()
6944 ));
6945 }
6946
6947 #[test]
6948 fn validate_typed_br_table_multi_block_targets_with_equivalent_signature() {
6949 let bytes = [
6950 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7f,
6951 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
6952 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x1a, 0x02,
6953 0x04, 0x00, 0x20, 0x00, 0x0b, 0x13, 0x00, 0x02, 0x63, 0x01, 0x02, 0x63, 0x00, 0xd2,
6954 0x00, 0x20, 0x00, 0x0e, 0x02, 0x00, 0x01, 0x01, 0x0b, 0x0b, 0x0b,
6955 ];
6956 let module = Module::decode(&bytes).unwrap();
6957 module.validate().unwrap();
6958 }
6959
6960 #[test]
6961 fn reject_typed_br_table_multi_block_targets_with_wrong_concrete_type() {
6962 let bytes = [
6963 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7e,
6964 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
6965 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x1a, 0x02,
6966 0x04, 0x00, 0x20, 0x00, 0x0b, 0x13, 0x00, 0x02, 0x63, 0x01, 0x02, 0x63, 0x00, 0xd2,
6967 0x00, 0x20, 0x00, 0x0e, 0x02, 0x00, 0x01, 0x01, 0x0b, 0x0b, 0x0b,
6968 ];
6969 let module = Module::decode(&bytes).unwrap();
6970 let err = module.validate().unwrap_err();
6971 assert_eq!(err.offset, ByteOffset(59));
6972 assert!(matches!(
6975 err.kind,
6976 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
6977 if label == crate::types::LabelIdx(1)
6978 && expected == vec![ValType::Ref(RefType::Typed {
6979 nullable: true,
6980 heap: crate::types::HeapType::Type(TypeIdx(1)),
6981 })]
6982 && found == vec![ValType::Ref(RefType::Typed {
6983 nullable: false,
6984 heap: crate::types::HeapType::Type(TypeIdx(0)),
6985 })]
6986 ));
6987 }
6988
6989 #[test]
6990 fn validate_typed_br_table_multi_loop_block_targets_with_equivalent_signature() {
6991 let bytes = [
6992 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x04, 0x60, 0x01, 0x7f,
6993 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x60,
6994 0x01, 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01,
6995 0x01, 0x66, 0x00, 0x00, 0x0a, 0x1e, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x17, 0x00,
6996 0x02, 0x63, 0x01, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x20, 0x00, 0x0e, 0x02,
6997 0x00, 0x01, 0x01, 0xd0, 0x00, 0x0b, 0x0b, 0x0b,
6998 ];
6999 let module = Module::decode(&bytes).unwrap();
7000 module.validate().unwrap();
7001 }
7002
7003 #[test]
7004 fn reject_typed_br_table_multi_loop_block_targets_with_wrong_concrete_type() {
7005 let bytes = [
7006 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x04, 0x60, 0x01, 0x7e,
7007 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x60,
7008 0x01, 0x63, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01,
7009 0x01, 0x66, 0x00, 0x00, 0x0a, 0x1e, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x17, 0x00,
7010 0x02, 0x63, 0x01, 0xd0, 0x00, 0x03, 0x03, 0x1a, 0xd2, 0x00, 0x20, 0x00, 0x0e, 0x02,
7011 0x00, 0x01, 0x01, 0xd0, 0x00, 0x0b, 0x0b, 0x0b,
7012 ];
7013 let module = Module::decode(&bytes).unwrap();
7014 let err = module.validate().unwrap_err();
7015 assert_eq!(err.offset, ByteOffset(68));
7016 assert!(matches!(
7019 err.kind,
7020 ValidationErrorKind::BranchTypeMismatch { label, expected, found }
7021 if label == crate::types::LabelIdx(1)
7022 && expected == vec![ValType::Ref(RefType::Typed {
7023 nullable: true,
7024 heap: crate::types::HeapType::Type(TypeIdx(1)),
7025 })]
7026 && found == vec![ValType::Ref(RefType::Typed {
7027 nullable: false,
7028 heap: crate::types::HeapType::Type(TypeIdx(0)),
7029 })]
7030 ));
7031 }
7032
7033 #[test]
7034 fn validate_start_function_with_empty_signature() {
7035 let bytes = [
7036 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
7037 0x03, 0x02, 0x01, 0x00, 0x08, 0x01, 0x00, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
7038 ];
7039 let module = Module::decode(&bytes).unwrap();
7040 module.validate().unwrap();
7041 }
7042
7043 #[test]
7044 fn reject_unknown_start_function_index() {
7045 let bytes = [
7046 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
7047 ];
7048 let module = Module::decode(&bytes).unwrap();
7049 let err = module.validate().unwrap_err();
7050 assert_eq!(err.offset, ByteOffset(10));
7051 assert!(matches!(
7052 err.kind,
7053 ValidationErrorKind::UnknownFuncIdx {
7054 idx: crate::types::FuncIdx(0)
7055 }
7056 ));
7057 }
7058
7059 #[test]
7060 fn reject_start_function_with_params() {
7061 let bytes = [
7062 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x01, 0x7F,
7063 0x00, 0x03, 0x02, 0x01, 0x00, 0x08, 0x01, 0x00, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
7064 ];
7065 let module = Module::decode(&bytes).unwrap();
7066 let err = module.validate().unwrap_err();
7067 assert_eq!(err.offset, ByteOffset(21));
7068 assert!(matches!(
7069 err.kind,
7070 ValidationErrorKind::InvalidStartFunctionType { params, results }
7071 if params == vec![ValType::Num(crate::types::NumType::I32)]
7072 && results.is_empty()
7073 ));
7074 }
7075
7076 #[test]
7077 fn reject_start_function_with_results() {
7078 let bytes = [
7079 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
7080 0x7F, 0x03, 0x02, 0x01, 0x00, 0x08, 0x01, 0x00, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
7081 ];
7082 let module = Module::decode(&bytes).unwrap();
7083 let err = module.validate().unwrap_err();
7084 assert_eq!(err.offset, ByteOffset(21));
7085 assert!(matches!(
7086 err.kind,
7087 ValidationErrorKind::InvalidStartFunctionType { params, results }
7088 if params.is_empty()
7089 && results == vec![ValType::Num(crate::types::NumType::I32)]
7090 ));
7091 }
7092
7093 #[test]
7094 fn validate_element_expression_initializers() {
7095 let bytes = [
7096 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
7097 0x03, 0x02, 0x01, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01, 0x09, 0x0A, 0x01, 0x05,
7098 0x70, 0x02, 0xD0, 0x70, 0x0B, 0xD2, 0x00, 0x0B, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
7099 ];
7100 let module = Module::decode(&bytes).unwrap();
7101 module.validate().unwrap();
7102 }
7103
7104 #[test]
7105 fn reject_element_expr_type_mismatch() {
7106 let bytes = [
7107 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x01, 0x6F, 0x00, 0x01,
7108 0x09, 0x07, 0x01, 0x05, 0x6F, 0x01, 0xD0, 0x70, 0x0B,
7109 ];
7110 let module = Module::decode(&bytes).unwrap();
7111 let err = module.validate().unwrap_err();
7112 assert!(matches!(
7113 err.kind,
7114 ValidationErrorKind::ElementExprTypeMismatch {
7115 expected: ValType::Ref(RefType::ExternRef),
7116 found: ValType::Ref(RefType::FuncRef),
7117 }
7118 ));
7119 }
7120
7121 #[test]
7122 fn reject_non_constant_element_expr() {
7123 let bytes = [
7124 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01,
7125 0x09, 0x07, 0x01, 0x05, 0x70, 0x01, 0x41, 0x00, 0x0B,
7126 ];
7127 let module = Module::decode(&bytes).unwrap();
7128 let err = module.validate().unwrap_err();
7129 assert!(matches!(
7130 err.kind,
7131 ValidationErrorKind::NonConstantElementExpr
7132 ));
7133 }
7134
7135 #[test]
7136 fn reject_memory_init_without_data_count_section() {
7137 let bytes = [
7138 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
7139 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x0A, 0x0E, 0x01, 0x0C, 0x00,
7140 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x08, 0x00, 0x00, 0x0B, 0x0B, 0x03, 0x01,
7141 0x01, 0x00,
7142 ];
7143 let module = Module::decode(&bytes).unwrap();
7144 let err = module.validate().unwrap_err();
7145 assert!(matches!(
7146 err.kind,
7147 ValidationErrorKind::MissingDataCountSection { op: "memory.init" }
7148 ));
7149 }
7150
7151 #[test]
7152 fn reject_data_drop_without_data_count_section() {
7153 let bytes = [
7154 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
7155 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0xFC, 0x09, 0x00, 0x0B,
7156 ];
7157 let module = Module::decode(&bytes).unwrap();
7158 let err = module.validate().unwrap_err();
7159 assert!(matches!(
7160 err.kind,
7161 ValidationErrorKind::MissingDataCountSection { op: "data.drop" }
7162 ));
7163 }
7164
7165 #[test]
7166 fn reject_active_element_table_type_mismatch() {
7167 let bytes = [
7168 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x01, 0x6F, 0x00, 0x01,
7169 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
7170 ];
7171 let module = Module::decode(&bytes).unwrap();
7172 let err = module.validate().unwrap_err();
7173 assert!(matches!(
7174 err.kind,
7175 ValidationErrorKind::ElementTableTypeMismatch {
7176 expected: RefType::ExternRef,
7177 found: RefType::FuncRef,
7178 }
7179 ));
7180 }
7181
7182 #[test]
7183 fn validate_active_element_table_type_match_for_imported_table() {
7184 let bytes = [
7185 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x01, 0x03, b'e', b'n',
7186 b'v', 0x01, b't', 0x01, 0x6F, 0x00, 0x01, 0x09, 0x0B, 0x01, 0x06, 0x00, 0x41, 0x00,
7187 0x0B, 0x6F, 0x01, 0xD0, 0x6F, 0x0B,
7188 ];
7189 let module = Module::decode(&bytes).unwrap();
7190 module.validate().unwrap();
7191 }
7192
7193 #[test]
7194 fn validate_multiple_tables_across_imports_and_definitions() {
7195 let bytes = [
7196 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x01, 0x03, b'e', b'n',
7197 b'v', 0x01, b't', 0x01, 0x70, 0x00, 0x01, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01,
7198 ];
7199 let module = Module::decode(&bytes).unwrap();
7200 module.validate().unwrap();
7201 }
7202
7203 #[test]
7204 fn validate_multiple_memories_across_imports_and_definitions() {
7205 let bytes = [
7206 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x02, 0x0C, 0x01, 0x03, b'e', b'n',
7207 b'v', 0x03, b'm', b'e', b'm', 0x02, 0x00, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01,
7208 ];
7209 let module = Module::decode(&bytes).unwrap();
7210 module.validate().unwrap();
7211 }
7212
7213 #[test]
7214 fn reject_duplicate_export_names() {
7215 let bytes = [
7216 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
7217 0x03, 0x02, 0x01, 0x00, 0x07, 0x0D, 0x02, 0x03, b'd', b'u', b'p', 0x00, 0x00, 0x03,
7218 b'd', b'u', b'p', 0x00, 0x00, 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B,
7219 ];
7220 let module = Module::decode(&bytes).unwrap();
7221 let err = module.validate().unwrap_err();
7222 assert!(matches!(
7223 err.kind,
7224 ValidationErrorKind::DuplicateExportName { name } if name == "dup"
7225 ));
7226 }
7227
7228 #[test]
7229 fn validate_exports_and_elements_indices() {
7230 let bytes = [
7231 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x00,
7232 0x60, 0x01, 0x7F, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x04, 0x01, 0x70, 0x00,
7233 0x02, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x06, 0x01, 0x7F, 0x00, 0x41, 0x00, 0x0B,
7234 0x07, 0x11, 0x04, 0x01, b'f', 0x00, 0x00, 0x01, b't', 0x01, 0x00, 0x01, b'm', 0x02,
7235 0x00, 0x01, b'g', 0x03, 0x00, 0x09, 0x08, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x02, 0x00,
7236 0x01, 0x0A, 0x07, 0x02, 0x02, 0x00, 0x0B, 0x02, 0x00, 0x0B,
7237 ];
7238 let module = Module::decode(&bytes).unwrap();
7239 module.validate().unwrap();
7240 }
7241
7242 #[test]
7243 fn reject_unknown_export_table_index() {
7244 let bytes = [
7245 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x01, b't', 0x01,
7246 0x00,
7247 ];
7248 let module = Module::decode(&bytes).unwrap();
7249 let err = module.validate().unwrap_err();
7250 assert_eq!(err.offset, ByteOffset(10));
7251 assert!(matches!(
7252 err.kind,
7253 ValidationErrorKind::UnknownTableIdx {
7254 idx: crate::types::TableIdx(0),
7255 available: 0,
7256 }
7257 ));
7258 }
7259
7260 #[test]
7261 fn reject_unknown_export_memory_index() {
7262 let bytes = [
7263 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x01, b'm', 0x02,
7264 0x00,
7265 ];
7266 let module = Module::decode(&bytes).unwrap();
7267 let err = module.validate().unwrap_err();
7268 assert_eq!(err.offset, ByteOffset(10));
7269 assert!(matches!(
7270 err.kind,
7271 ValidationErrorKind::UnknownMemIdx {
7272 idx: crate::types::MemIdx(0),
7273 available: 0,
7274 }
7275 ));
7276 }
7277
7278 #[test]
7279 fn reject_unknown_export_global_index() {
7280 let bytes = [
7281 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x01, b'g', 0x03,
7282 0x00,
7283 ];
7284 let module = Module::decode(&bytes).unwrap();
7285 let err = module.validate().unwrap_err();
7286 assert_eq!(err.offset, ByteOffset(10));
7287 assert!(matches!(
7288 err.kind,
7289 ValidationErrorKind::UnknownGlobalIdx {
7290 idx: crate::types::GlobalIdx(0),
7291 available: 0,
7292 }
7293 ));
7294 }
7295
7296 #[test]
7297 fn reject_unknown_element_table_index() {
7298 let bytes = [
7299 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x09, 0x09, 0x01, 0x02, 0x00, 0x41,
7300 0x00, 0x0B, 0x00, 0x01, 0x00,
7301 ];
7302 let module = Module::decode(&bytes).unwrap();
7303 let err = module.validate().unwrap_err();
7304 assert_eq!(err.offset, ByteOffset(13));
7305 assert!(matches!(
7306 err.kind,
7307 ValidationErrorKind::UnknownTableIdx {
7308 idx: crate::types::TableIdx(0),
7309 available: 0,
7310 }
7311 ));
7312 }
7313
7314 #[test]
7315 fn reject_unknown_function_index_in_element_init() {
7316 let bytes = [
7317 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01,
7318 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
7319 ];
7320 let module = Module::decode(&bytes).unwrap();
7321 let err = module.validate().unwrap_err();
7322 assert_eq!(err.offset, ByteOffset(16));
7323 assert!(matches!(
7324 err.kind,
7325 ValidationErrorKind::UnknownFuncIdx {
7326 idx: crate::types::FuncIdx(0)
7327 }
7328 ));
7329 }
7330
7331 #[test]
7332 fn validate_call_indirect_with_funcref_table() {
7333 let bytes = [
7334 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, 0x01, 0x7F,
7335 0x01, 0x7F, 0x60, 0x00, 0x00, 0x02, 0x0D, 0x01, 0x03, b'e', b'n', b'v', 0x03, b't',
7336 b'a', b'b', 0x01, 0x70, 0x00, 0x01, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0B, 0x01, 0x09,
7337 0x00, 0x20, 0x00, 0x41, 0x00, 0x11, 0x00, 0x00, 0x0B,
7338 ];
7339 let module = Module::decode(&bytes).unwrap();
7340 module.validate().unwrap();
7341 }
7342
7343 #[test]
7344 fn validate_typed_block_result_to_call_indirect_ref_param_with_equivalent_signature() {
7345 let bytes = include_bytes!(
7346 "../../../baedeker-testdata/spec/valid/typed-block-to-call-indirect-ref-param-equivalent-signature.wasm",
7347 );
7348 let module = Module::decode(bytes).unwrap();
7349 module.validate().unwrap();
7350 }
7351
7352 #[test]
7353 fn reject_typed_block_result_to_call_indirect_ref_param_with_wrong_concrete_type() {
7354 let bytes = include_bytes!(
7355 "../../../baedeker-testdata/spec/invalid-validate/typed-block-to-call-indirect-ref-param-wrong-concrete-type.wasm",
7356 );
7357 let module = Module::decode(bytes).unwrap();
7358 let err = module.validate().unwrap_err();
7359 assert_eq!(err.offset, ByteOffset(88));
7360 assert!(matches!(
7361 err.kind,
7362 ValidationErrorKind::TypeMismatch { op, expected, found }
7363 if op == "stack"
7364 && expected == ValType::Ref(RefType::Typed {
7365 nullable: true,
7366 heap: crate::types::HeapType::Type(TypeIdx(1)),
7367 })
7368 && found == ValType::Ref(RefType::Typed {
7369 nullable: true,
7370 heap: crate::types::HeapType::Type(TypeIdx(0)),
7371 })
7372 ));
7373 }
7374
7375 #[test]
7376 fn validate_return_call() {
7377 let bytes = [
7378 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
7379 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x0A, 0x0B, 0x02, 0x04, 0x00, 0x41, 0x00, 0x0B,
7380 0x04, 0x00, 0x12, 0x00, 0x0B,
7381 ];
7382 let module = Module::decode(&bytes).unwrap();
7383 module.validate().unwrap();
7384 }
7385
7386 #[test]
7387 fn reject_return_call_result_mismatch() {
7388 let bytes = [
7389 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, 0x00, 0x01,
7390 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x03, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0B, 0x02, 0x04,
7391 0x00, 0x42, 0x00, 0x0B, 0x04, 0x00, 0x12, 0x00, 0x0B,
7392 ];
7393 let module = Module::decode(&bytes).unwrap();
7394 let err = module.validate().unwrap_err();
7395 assert_eq!(err.offset, ByteOffset(34));
7396 assert!(matches!(
7397 err.kind,
7398 ValidationErrorKind::ResultTypeMismatch {
7399 expected,
7400 found,
7401 } if expected == vec![ValType::Num(crate::types::NumType::I32)]
7402 && found == vec![ValType::Num(crate::types::NumType::I64)]
7403 ));
7404 }
7405
7406 #[test]
7407 fn validate_return_call_indirect_with_funcref_table() {
7408 let bytes = [
7409 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F,
7410 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00, 0x01, 0x0A,
7411 0x10, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x09, 0x00, 0x20, 0x00, 0x41, 0x00, 0x13,
7412 0x00, 0x00, 0x0B,
7413 ];
7414 let module = Module::decode(&bytes).unwrap();
7415 module.validate().unwrap();
7416 }
7417
7418 #[test]
7419 fn validate_typed_table_init_to_return_call_indirect_result_nullable_official_case() {
7420 let bytes = include_bytes!(
7421 "../../../baedeker-testdata/spec/valid/typed-table-init-to-return-call-indirect-result-nullable.wasm",
7422 );
7423 let module = Module::decode(bytes).unwrap();
7424 module.validate().unwrap();
7425 }
7426
7427 #[test]
7428 fn validate_typed_if_result_to_return_call_indirect_ref_param_with_equivalent_signature() {
7429 let bytes = include_bytes!(
7430 "../../../baedeker-testdata/spec/valid/typed-if-to-return-call-indirect-ref-param-equivalent-signature.wasm",
7431 );
7432 let module = Module::decode(bytes).unwrap();
7433 module.validate().unwrap();
7434 }
7435
7436 #[test]
7437 fn reject_typed_if_result_to_return_call_indirect_ref_param_with_wrong_concrete_type() {
7438 let bytes = include_bytes!(
7439 "../../../baedeker-testdata/spec/invalid-validate/typed-if-to-return-call-indirect-ref-param-wrong-concrete-type.wasm",
7440 );
7441 let module = Module::decode(bytes).unwrap();
7442 let err = module.validate().unwrap_err();
7443 assert_eq!(err.offset, ByteOffset(89));
7444 assert!(matches!(
7445 err.kind,
7446 ValidationErrorKind::TypeMismatch { op, expected, found }
7447 if op == "stack"
7448 && expected == ValType::Ref(RefType::Typed {
7449 nullable: true,
7450 heap: crate::types::HeapType::Type(TypeIdx(1)),
7451 })
7452 && found == ValType::Ref(RefType::Typed {
7453 nullable: true,
7454 heap: crate::types::HeapType::Type(TypeIdx(0)),
7455 })
7456 ));
7457 }
7458
7459 #[test]
7460 fn reject_typed_table_init_to_return_call_indirect_result_nullability_mismatch() {
7461 let bytes = include_bytes!(
7462 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-to-return-call-indirect-result-nullability-mismatch.wasm",
7463 );
7464 let module = Module::decode(bytes).unwrap();
7465 let err = module.validate().unwrap_err();
7466 assert_eq!(err.offset, ByteOffset(81));
7467 assert!(matches!(
7468 err.kind,
7469 ValidationErrorKind::ResultTypeMismatch { expected, found }
7470 if expected == vec![ValType::Ref(RefType::Typed {
7471 nullable: false,
7472 heap: crate::types::HeapType::Type(TypeIdx(0)),
7473 })] && found == vec![ValType::Ref(RefType::Typed {
7474 nullable: true,
7475 heap: crate::types::HeapType::Type(TypeIdx(0)),
7476 })]
7477 ));
7478 }
7479
7480 #[test]
7481 fn validate_typed_table_init_shared_source_to_return_call_indirect_result_nullable_official_case()
7482 {
7483 let bytes = include_bytes!(
7484 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-return-call-indirect-result-nullable.wasm",
7485 );
7486 let module = Module::decode(bytes).unwrap();
7487 module.validate().unwrap();
7488 }
7489
7490 #[test]
7491 fn reject_typed_table_init_shared_source_to_return_call_indirect_result_nullability_mismatch() {
7492 let bytes = include_bytes!(
7493 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-return-call-indirect-result-nullability-mismatch.wasm",
7494 );
7495 let module = Module::decode(bytes).unwrap();
7496 let err = module.validate().unwrap_err();
7497 assert_eq!(err.offset, ByteOffset(130));
7498 assert!(matches!(
7499 err.kind,
7500 ValidationErrorKind::ResultTypeMismatch { expected, found }
7501 if expected == vec![ValType::Ref(RefType::Typed {
7502 nullable: false,
7503 heap: crate::types::HeapType::Type(TypeIdx(0)),
7504 })] && found == vec![ValType::Ref(RefType::Typed {
7505 nullable: true,
7506 heap: crate::types::HeapType::Type(TypeIdx(0)),
7507 })]
7508 ));
7509 }
7510
7511 #[test]
7512 fn validate_call_ref() {
7513 let bytes = [
7514 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F,
7515 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00,
7516 0x0A, 0x0F, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x08, 0x00, 0x41, 0x07, 0xD2, 0x00,
7517 0x14, 0x00, 0x0B,
7518 ];
7519 let module = Module::decode(&bytes).unwrap();
7520 module.validate().unwrap();
7521 }
7522
7523 #[test]
7524 fn validate_call_ref_with_equivalent_concrete_type() {
7525 let bytes = [
7526 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7527 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x07, 0x05,
7528 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x0F, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x08,
7529 0x00, 0x20, 0x00, 0xD2, 0x00, 0x14, 0x01, 0x0B,
7530 ];
7531 let module = Module::decode(&bytes).unwrap();
7532 module.validate().unwrap();
7533 }
7534
7535 #[test]
7536 fn validate_typed_block_result_to_call_ref_with_equivalent_signature() {
7537 let bytes = include_bytes!(
7538 "../../../baedeker-testdata/spec/valid/typed-block-to-call-ref-equivalent-signature.wasm",
7539 );
7540 let module = Module::decode(bytes).unwrap();
7541 module.validate().unwrap();
7542 }
7543
7544 #[test]
7545 fn validate_typed_call_ref_if_nullable_official_case() {
7546 let bytes = include_bytes!(
7547 "../../../baedeker-testdata/spec/valid/typed-call-ref-if-nullable.wasm",
7548 );
7549 let module = Module::decode(bytes).unwrap();
7550 module.validate().unwrap();
7551 }
7552
7553 #[test]
7554 fn reject_typed_call_ref_if_abstract_nullability_mismatch() {
7555 let bytes = include_bytes!(
7556 "../../../baedeker-testdata/spec/invalid-validate/typed-call-ref-if-abstract-nullability-mismatch.wasm",
7557 );
7558 let module = Module::decode(bytes).unwrap();
7559 let err = module.validate().unwrap_err();
7560 assert_eq!(err.offset, ByteOffset(56));
7561 assert!(matches!(
7562 err.kind,
7563 ValidationErrorKind::TypeMismatch { op, expected, found }
7564 if op == "call_ref"
7565 && expected == ValType::Ref(RefType::Typed {
7566 nullable: true,
7567 heap: crate::types::HeapType::Type(TypeIdx(0)),
7568 })
7569 && found == ValType::Ref(RefType::FuncRef)
7570 ));
7571 }
7572
7573 #[test]
7574 fn validate_call_ref_run_nested_official_case() {
7575 let bytes =
7576 include_bytes!("../../../baedeker-testdata/spec/valid/call-ref-run-nested.wasm");
7577 let module = Module::decode(bytes).unwrap();
7578 module.validate().unwrap();
7579 }
7580
7581 #[test]
7582 fn validate_call_ref_unreachable_ref_func_official_case() {
7583 let bytes = include_bytes!(
7584 "../../../baedeker-testdata/spec/valid/call-ref-unreachable-ref-func.wasm",
7585 );
7586 let module = Module::decode(bytes).unwrap();
7587 module.validate().unwrap();
7588 }
7589
7590 #[test]
7591 fn validate_call_ref_unreachable_call_drop_official_case() {
7592 let bytes = include_bytes!(
7593 "../../../baedeker-testdata/spec/valid/call-ref-unreachable-call-drop.wasm",
7594 );
7595 let module = Module::decode(bytes).unwrap();
7596 module.validate().unwrap();
7597 }
7598
7599 #[test]
7600 fn reject_typed_call_ref_function_result_wrong_concrete_type() {
7601 let bytes = include_bytes!(
7602 "../../../baedeker-testdata/spec/invalid-validate/typed-call-ref-function-result-wrong-concrete-type.wasm",
7603 );
7604 let module = Module::decode(bytes).unwrap();
7605 let err = module.validate().unwrap_err();
7606 assert_eq!(err.offset, ByteOffset(57));
7607 assert!(matches!(
7608 err.kind,
7609 ValidationErrorKind::FunctionResultTypeMismatch {
7610 expected,
7611 found,
7612 ..
7613 } if expected == vec![ValType::Ref(RefType::Typed {
7614 nullable: true,
7615 heap: crate::types::HeapType::Type(TypeIdx(1)),
7616 })] && found == vec![ValType::Ref(RefType::Typed {
7617 nullable: true,
7618 heap: crate::types::HeapType::Type(TypeIdx(0)),
7619 })]
7620 ));
7621 }
7622
7623 #[test]
7624 fn reject_typed_call_ref_block_result_wrong_concrete_type() {
7625 let bytes = include_bytes!(
7626 "../../../baedeker-testdata/spec/invalid-validate/typed-call-ref-block-result-wrong-concrete-type.wasm",
7627 );
7628 let module = Module::decode(bytes).unwrap();
7629 let err = module.validate().unwrap_err();
7630 assert_eq!(err.offset, ByteOffset(60));
7631 assert!(matches!(
7632 err.kind,
7633 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
7634 if expected == vec![ValType::Ref(RefType::Typed {
7635 nullable: true,
7636 heap: crate::types::HeapType::Type(TypeIdx(1)),
7637 })] && found == vec![ValType::Ref(RefType::Typed {
7638 nullable: true,
7639 heap: crate::types::HeapType::Type(TypeIdx(0)),
7640 })]
7641 ));
7642 }
7643
7644 #[test]
7645 fn reject_typed_call_ref_if_result_wrong_concrete_type() {
7646 let bytes = include_bytes!(
7647 "../../../baedeker-testdata/spec/invalid-validate/typed-call-ref-if-result-wrong-concrete-type.wasm",
7648 );
7649 let module = Module::decode(bytes).unwrap();
7650 let err = module.validate().unwrap_err();
7651 assert_eq!(err.offset, ByteOffset(63));
7652 assert!(matches!(
7653 err.kind,
7654 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
7655 if expected == vec![ValType::Ref(RefType::Typed {
7656 nullable: true,
7657 heap: crate::types::HeapType::Type(TypeIdx(1)),
7658 })] && found == vec![ValType::Ref(RefType::Typed {
7659 nullable: true,
7660 heap: crate::types::HeapType::Type(TypeIdx(0)),
7661 })]
7662 ));
7663 }
7664
7665 #[test]
7666 fn reject_typed_block_result_to_call_ref_with_wrong_concrete_type() {
7667 let bytes = include_bytes!(
7668 "../../../baedeker-testdata/spec/invalid-validate/typed-block-to-call-ref-wrong-concrete-type.wasm",
7669 );
7670 let module = Module::decode(bytes).unwrap();
7671 let err = module.validate().unwrap_err();
7672 assert_eq!(err.offset, ByteOffset(51));
7673 assert!(matches!(
7674 err.kind,
7675 ValidationErrorKind::TypeMismatch { op, expected, found }
7676 if op == "call_ref"
7677 && expected == ValType::Ref(RefType::Typed {
7678 nullable: true,
7679 heap: crate::types::HeapType::Type(TypeIdx(1)),
7680 })
7681 && found == ValType::Ref(RefType::Typed {
7682 nullable: true,
7683 heap: crate::types::HeapType::Type(TypeIdx(0)),
7684 })
7685 ));
7686 }
7687
7688 #[test]
7689 fn validate_typed_ref_global_init_from_ref_func() {
7690 let bytes = [
7691 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F,
7692 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x06, 0x07, 0x01, 0x63, 0x00, 0x00, 0xD2, 0x00,
7693 0x0B, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x06, 0x01, 0x04, 0x00, 0x20,
7694 0x00, 0x0B,
7695 ];
7696 let module = Module::decode(&bytes).unwrap();
7697 module.validate().unwrap();
7698 }
7699
7700 #[test]
7701 fn validate_typed_ref_global_init_from_equivalent_ref_func() {
7702 let bytes = [
7703 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7704 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x06, 0x07, 0x01,
7705 0x63, 0x01, 0x00, 0xD2, 0x00, 0x0B, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A,
7706 0x06, 0x01, 0x04, 0x00, 0x20, 0x00, 0x0B,
7707 ];
7708 let module = Module::decode(&bytes).unwrap();
7709 module.validate().unwrap();
7710 }
7711
7712 #[test]
7713 fn validate_typed_ref_global_init_from_imported_typed_global_with_equivalent_signature() {
7714 let bytes = [
7715 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7716 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x02, 0x0B, 0x01, 0x03, 0x65, 0x6E, 0x76,
7717 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x06, 0x07, 0x01, 0x63, 0x01, 0x00, 0x23, 0x00,
7718 0x0B,
7719 ];
7720 let module = Module::decode(&bytes).unwrap();
7721 module.validate().unwrap();
7722 }
7723
7724 #[test]
7725 fn validate_typed_ref_global_init_from_defined_typed_global_with_equivalent_signature() {
7726 let bytes = [
7727 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7728 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x06, 0x0D, 0x02,
7729 0x63, 0x00, 0x00, 0xD2, 0x00, 0x0B, 0x63, 0x01, 0x00, 0x23, 0x00, 0x0B, 0x07, 0x05,
7730 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x06, 0x01, 0x04, 0x00, 0x20, 0x00, 0x0B,
7731 ];
7732 let module = Module::decode(&bytes).unwrap();
7733 module.validate().unwrap();
7734 }
7735
7736 #[test]
7737 fn validate_ref_func_to_imported_mut_typed_global_with_equivalent_signature() {
7738 let bytes = [
7739 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x03, 0x60, 0x01, 0x7F,
7740 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x02, 0x0B, 0x01, 0x03,
7741 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x63, 0x01, 0x01, 0x03, 0x03, 0x02, 0x00, 0x02,
7742 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x0D, 0x02, 0x04, 0x00, 0x20, 0x00,
7743 0x0B, 0x06, 0x00, 0xD2, 0x00, 0x24, 0x00, 0x0B,
7744 ];
7745 let module = Module::decode(&bytes).unwrap();
7746 module.validate().unwrap();
7747 }
7748
7749 #[test]
7750 fn validate_typed_table_get_to_defined_mut_global_with_equivalent_signature() {
7751 let bytes = include_bytes!(
7752 "../../../baedeker-testdata/spec/valid/typed-table-to-defined-mut-global-equivalent-signature.wasm",
7753 );
7754 let module = Module::decode(bytes).unwrap();
7755 module.validate().unwrap();
7756 }
7757
7758 #[test]
7759 fn validate_imported_typed_table_get_to_defined_mut_global_with_equivalent_signature() {
7760 let bytes = include_bytes!(
7761 "../../../baedeker-testdata/spec/valid/imported-typed-table-to-defined-mut-global-equivalent-signature.wasm",
7762 );
7763 let module = Module::decode(bytes).unwrap();
7764 module.validate().unwrap();
7765 }
7766
7767 #[test]
7768 fn validate_typed_local_set_if_nullable_official_case() {
7769 let bytes = include_bytes!(
7770 "../../../baedeker-testdata/spec/valid/typed-local-set-if-nullable.wasm",
7771 );
7772 let module = Module::decode(bytes).unwrap();
7773 module.validate().unwrap();
7774 }
7775
7776 #[test]
7777 fn validate_typed_local_if_nullable_to_call_ref_official_case() {
7778 let bytes = include_bytes!(
7779 "../../../baedeker-testdata/spec/valid/typed-local-if-nullable-to-call-ref.wasm",
7780 );
7781 let module = Module::decode(bytes).unwrap();
7782 module.validate().unwrap();
7783 }
7784
7785 #[test]
7786 fn validate_typed_global_set_if_nullable_official_case() {
7787 let bytes = include_bytes!(
7788 "../../../baedeker-testdata/spec/valid/typed-global-set-if-nullable.wasm",
7789 );
7790 let module = Module::decode(bytes).unwrap();
7791 module.validate().unwrap();
7792 }
7793
7794 #[test]
7795 fn validate_typed_table_init_shared_source_to_global_set_nullable_official_case() {
7796 let bytes = include_bytes!(
7797 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-global-set-nullable.wasm",
7798 );
7799 let module = Module::decode(bytes).unwrap();
7800 module.validate().unwrap();
7801 }
7802
7803 #[test]
7804 fn validate_typed_global_if_nullable_to_call_ref_official_case() {
7805 let bytes = include_bytes!(
7806 "../../../baedeker-testdata/spec/valid/typed-global-if-nullable-to-call-ref.wasm",
7807 );
7808 let module = Module::decode(bytes).unwrap();
7809 module.validate().unwrap();
7810 }
7811
7812 #[test]
7813 fn validate_typed_table_set_if_nullable_official_case() {
7814 let bytes = include_bytes!(
7815 "../../../baedeker-testdata/spec/valid/typed-table-set-if-nullable.wasm",
7816 );
7817 let module = Module::decode(bytes).unwrap();
7818 module.validate().unwrap();
7819 }
7820
7821 #[test]
7822 fn validate_typed_table_if_nullable_to_call_ref_official_case() {
7823 let bytes = include_bytes!(
7824 "../../../baedeker-testdata/spec/valid/typed-table-if-nullable-to-call-ref.wasm",
7825 );
7826 let module = Module::decode(bytes).unwrap();
7827 module.validate().unwrap();
7828 }
7829
7830 #[test]
7831 fn validate_typed_passive_element_nullable_from_nonnull_official_case() {
7832 let bytes = include_bytes!(
7833 "../../../baedeker-testdata/spec/valid/typed-passive-element-nullable-from-nonnull.wasm",
7834 );
7835 let module = Module::decode(bytes).unwrap();
7836 module.validate().unwrap();
7837 }
7838
7839 #[test]
7840 fn validate_typed_defined_nonnull_global_passive_element_nullable_official_case() {
7841 let bytes = include_bytes!(
7842 "../../../baedeker-testdata/spec/valid/typed-defined-nonnull-global-passive-element-nullable.wasm",
7843 );
7844 let module = Module::decode(bytes).unwrap();
7845 module.validate().unwrap();
7846 }
7847
7848 #[test]
7849 fn validate_typed_table_init_nullable_to_call_ref_official_case() {
7850 let bytes = include_bytes!(
7851 "../../../baedeker-testdata/spec/valid/typed-table-init-nullable-to-call-ref.wasm",
7852 );
7853 let module = Module::decode(bytes).unwrap();
7854 module.validate().unwrap();
7855 }
7856
7857 #[test]
7858 fn validate_typed_defined_global_passive_element_table_init_nullable_to_call_ref_official_case()
7859 {
7860 let bytes = include_bytes!(
7861 "../../../baedeker-testdata/spec/valid/typed-defined-global-passive-element-table-init-nullable-to-call-ref.wasm",
7862 );
7863 let module = Module::decode(bytes).unwrap();
7864 module.validate().unwrap();
7865 }
7866
7867 #[test]
7868 fn validate_typed_imported_global_passive_element_table_init_nullable_to_call_ref_official_case()
7869 {
7870 let bytes = include_bytes!(
7871 "../../../baedeker-testdata/spec/valid/typed-imported-global-passive-element-table-init-nullable-to-call-ref.wasm",
7872 );
7873 let module = Module::decode(bytes).unwrap();
7874 module.validate().unwrap();
7875 }
7876
7877 #[test]
7878 fn validate_typed_imported_nonnull_global_passive_element_table_init_nullable_to_call_ref_official_case()
7879 {
7880 let bytes = include_bytes!(
7881 "../../../baedeker-testdata/spec/valid/typed-imported-nonnull-global-passive-element-table-init-nullable-to-call-ref.wasm",
7882 );
7883 let module = Module::decode(bytes).unwrap();
7884 module.validate().unwrap();
7885 }
7886
7887 #[test]
7888 fn validate_typed_table_set_get() {
7889 let bytes = [
7890 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7891 0x01, 0x7F, 0x60, 0x00, 0x01, 0x63, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x05,
7892 0x01, 0x63, 0x00, 0x00, 0x01, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x13,
7893 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00, 0x41, 0x00, 0xD2, 0x00, 0x26, 0x00,
7894 0x41, 0x00, 0x25, 0x00, 0x0B,
7895 ];
7896 let module = Module::decode(&bytes).unwrap();
7897 module.validate().unwrap();
7898 }
7899
7900 #[test]
7901 fn validate_typed_table_set_get_with_equivalent_concrete_type() {
7902 let bytes = [
7903 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F,
7904 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
7905 0x02, 0x00, 0x02, 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x01, 0x07, 0x05, 0x01, 0x01,
7906 0x66, 0x00, 0x00, 0x0A, 0x13, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00, 0x41,
7907 0x00, 0xD2, 0x00, 0x26, 0x00, 0x41, 0x00, 0x25, 0x00, 0x0B,
7908 ];
7909 let module = Module::decode(&bytes).unwrap();
7910 module.validate().unwrap();
7911 }
7912
7913 #[test]
7914 fn validate_imported_typed_global_to_defined_table_with_equivalent_signature() {
7915 let bytes = [
7916 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F,
7917 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x01, 0x63, 0x01, 0x02, 0x0B,
7918 0x01, 0x03, 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x03, 0x02, 0x01,
7919 0x02, 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x01, 0x0A, 0x0E, 0x01, 0x0C, 0x00, 0x41,
7920 0x00, 0x23, 0x00, 0x26, 0x00, 0x41, 0x00, 0x25, 0x00, 0x0B,
7921 ];
7922 let module = Module::decode(&bytes).unwrap();
7923 module.validate().unwrap();
7924 }
7925
7926 #[test]
7927 fn validate_imported_typed_global_to_imported_table_with_equivalent_signature() {
7928 let bytes = [
7929 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F,
7930 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x01, 0x63, 0x01, 0x02, 0x16,
7931 0x02, 0x03, 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E,
7932 0x76, 0x01, 0x74, 0x01, 0x63, 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x02, 0x0A, 0x0E,
7933 0x01, 0x0C, 0x00, 0x41, 0x00, 0x23, 0x00, 0x26, 0x00, 0x41, 0x00, 0x25, 0x00, 0x0B,
7934 ];
7935 let module = Module::decode(&bytes).unwrap();
7936 module.validate().unwrap();
7937 }
7938
7939 #[test]
7940 fn validate_typed_element_expr_from_imported_typed_global_with_equivalent_signature() {
7941 let bytes = [
7942 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7943 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x02, 0x0B, 0x01, 0x03, 0x65, 0x6E, 0x76,
7944 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x01, 0x09,
7945 0x0C, 0x01, 0x06, 0x00, 0x41, 0x00, 0x0B, 0x63, 0x01, 0x01, 0x23, 0x00, 0x0B,
7946 ];
7947 let module = Module::decode(&bytes).unwrap();
7948 module.validate().unwrap();
7949 }
7950
7951 #[test]
7952 fn validate_typed_passive_element_from_equivalent_ref_func() {
7953 let bytes = [
7954 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
7955 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03, 0x02, 0x01, 0x00, 0x07, 0x05, 0x01,
7956 0x01, 0x66, 0x00, 0x00, 0x09, 0x08, 0x01, 0x05, 0x63, 0x01, 0x01, 0xD2, 0x00, 0x0B,
7957 0x0A, 0x06, 0x01, 0x04, 0x00, 0x20, 0x00, 0x0B,
7958 ];
7959 let module = Module::decode(&bytes).unwrap();
7960 module.validate().unwrap();
7961 }
7962
7963 #[test]
7964 fn validate_typed_passive_element_from_defined_typed_global_with_equivalent_signature() {
7965 let bytes = include_bytes!(
7966 "../../../baedeker-testdata/spec/valid/defined-typed-global-passive-element-equivalent-signature.wasm",
7967 );
7968 let module = Module::decode(bytes).unwrap();
7969 module.validate().unwrap();
7970 }
7971
7972 #[test]
7973 fn validate_typed_passive_element_from_imported_typed_global_with_equivalent_signature() {
7974 let bytes = include_bytes!(
7975 "../../../baedeker-testdata/spec/valid/imported-typed-global-passive-element-equivalent-signature.wasm",
7976 );
7977 let module = Module::decode(bytes).unwrap();
7978 module.validate().unwrap();
7979 }
7980
7981 #[test]
7982 fn validate_typed_table_init_from_defined_typed_global_passive_element_with_equivalent_signature()
7983 {
7984 let bytes = include_bytes!(
7985 "../../../baedeker-testdata/spec/valid/defined-typed-global-passive-element-table-init-equivalent-signature.wasm",
7986 );
7987 let module = Module::decode(bytes).unwrap();
7988 module.validate().unwrap();
7989 }
7990
7991 #[test]
7992 fn validate_typed_table_init_from_imported_typed_global_passive_element_with_equivalent_signature()
7993 {
7994 let bytes = include_bytes!(
7995 "../../../baedeker-testdata/spec/valid/imported-typed-global-passive-element-table-init-equivalent-signature.wasm",
7996 );
7997 let module = Module::decode(bytes).unwrap();
7998 module.validate().unwrap();
7999 }
8000
8001 #[test]
8002 fn validate_table_init_with_equivalent_typed_element_segment() {
8003 let bytes = [
8004 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x03, 0x60, 0x01, 0x7F,
8005 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00,
8006 0x02, 0x04, 0x05, 0x01, 0x63, 0x00, 0x00, 0x04, 0x07, 0x0C, 0x02, 0x01, 0x66, 0x00,
8007 0x00, 0x04, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x01, 0x09, 0x08, 0x01, 0x05, 0x63, 0x01,
8008 0x01, 0xD2, 0x00, 0x0B, 0x0A, 0x13, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00,
8009 0x41, 0x00, 0x41, 0x00, 0x41, 0x01, 0xFC, 0x0C, 0x00, 0x00, 0x0B,
8010 ];
8011 let module = Module::decode(&bytes).unwrap();
8012 module.validate().unwrap();
8013 }
8014
8015 #[test]
8016 fn validate_typed_block_result_with_equivalent_signature() {
8017 let bytes = [
8018 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F,
8019 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8020 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x13, 0x02, 0x04,
8021 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00, 0x02, 0x63, 0x01, 0xD2, 0x00, 0x0C, 0x00, 0xD0,
8022 0x01, 0x0B, 0x0B,
8023 ];
8024 let module = Module::decode(&bytes).unwrap();
8025 module.validate().unwrap();
8026 }
8027
8028 #[test]
8029 fn validate_typed_block_result_nullable_from_nonnull_official_case() {
8030 let bytes = include_bytes!(
8031 "../../../baedeker-testdata/spec/valid/typed-block-result-nullable-from-nonnull.wasm",
8032 );
8033 let module = Module::decode(bytes).unwrap();
8034 module.validate().unwrap();
8035 }
8036
8037 #[test]
8038 fn reject_typed_block_result_nullability_mismatch() {
8039 let bytes = include_bytes!(
8040 "../../../baedeker-testdata/spec/invalid-validate/typed-block-result-nullability-mismatch.wasm",
8041 );
8042 let module = Module::decode(bytes).unwrap();
8043 let err = module.validate().unwrap_err();
8044 assert_eq!(err.offset, ByteOffset(35));
8045 assert!(matches!(
8046 err.kind,
8047 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8048 if expected == vec![ValType::Ref(RefType::Typed {
8049 nullable: false,
8050 heap: crate::types::HeapType::Type(TypeIdx(0)),
8051 })] && found == vec![ValType::Ref(RefType::Typed {
8052 nullable: true,
8053 heap: crate::types::HeapType::Type(TypeIdx(0)),
8054 })]
8055 ));
8056 }
8057
8058 #[test]
8059 fn validate_typed_block_result_feeds_loop_param_with_equivalent_signature() {
8060 let bytes = [
8061 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7f,
8062 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x60, 0x01,
8063 0x63, 0x01, 0x01, 0x63, 0x01, 0x03, 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01,
8064 0x66, 0x00, 0x00, 0x0a, 0x12, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0b, 0x00, 0x02,
8065 0x63, 0x00, 0xd2, 0x00, 0x0b, 0x03, 0x03, 0x0b, 0x0b,
8066 ];
8067 let module = Module::decode(&bytes).unwrap();
8068 module.validate().unwrap();
8069 }
8070
8071 #[test]
8072 fn reject_typed_block_result_feeds_loop_param_with_wrong_concrete_type() {
8073 let bytes = [
8074 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x17, 0x04, 0x60, 0x01, 0x7e,
8075 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x60, 0x01,
8076 0x63, 0x01, 0x01, 0x63, 0x01, 0x03, 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01,
8077 0x66, 0x00, 0x00, 0x0a, 0x12, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0b, 0x00, 0x02,
8078 0x63, 0x00, 0xd2, 0x00, 0x0b, 0x03, 0x03, 0x0b, 0x0b,
8079 ];
8080 let module = Module::decode(&bytes).unwrap();
8081 let err = module.validate().unwrap_err();
8082 assert_eq!(err.offset, ByteOffset(61));
8083 assert!(matches!(
8084 err.kind,
8085 ValidationErrorKind::TypeMismatch { op, expected, found }
8086 if op == "stack"
8087 && expected == ValType::Ref(RefType::Typed {
8088 nullable: true,
8089 heap: crate::types::HeapType::Type(TypeIdx(1)),
8090 })
8091 && found == ValType::Ref(RefType::Typed {
8092 nullable: true,
8093 heap: crate::types::HeapType::Type(TypeIdx(0)),
8094 })
8095 ));
8096 }
8097
8098 #[test]
8099 fn validate_typed_loop_result_feeds_block_result_with_equivalent_signature() {
8100 let bytes = [
8101 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
8102 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8103 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x13, 0x02, 0x04,
8104 0x00, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x02, 0x63, 0x01, 0x03, 0x63, 0x00, 0xd2, 0x00,
8105 0x0b, 0x0b, 0x0b,
8106 ];
8107 let module = Module::decode(&bytes).unwrap();
8108 module.validate().unwrap();
8109 }
8110
8111 #[test]
8112 fn reject_typed_loop_result_feeds_block_result_with_wrong_concrete_type() {
8113 let bytes = [
8114 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7e,
8115 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8116 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x13, 0x02, 0x04,
8117 0x00, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x02, 0x63, 0x01, 0x03, 0x63, 0x00, 0xd2, 0x00,
8118 0x0b, 0x0b, 0x0b,
8119 ];
8120 let module = Module::decode(&bytes).unwrap();
8121 let err = module.validate().unwrap_err();
8122 assert_eq!(err.offset, ByteOffset(57));
8123 assert!(matches!(
8124 err.kind,
8125 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8126 if expected == vec![ValType::Ref(RefType::Typed {
8127 nullable: true,
8128 heap: crate::types::HeapType::Type(TypeIdx(1)),
8129 })] && found == vec![ValType::Ref(RefType::Typed {
8130 nullable: true,
8131 heap: crate::types::HeapType::Type(TypeIdx(0)),
8132 })]
8133 ));
8134 }
8135
8136 #[test]
8137 fn validate_typed_if_result_with_equivalent_signature() {
8138 let bytes = [
8139 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7F,
8140 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x63, 0x01, 0x03,
8141 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x14, 0x02,
8142 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0D, 0x00, 0x20, 0x00, 0x04, 0x63, 0x01, 0xD2, 0x00,
8143 0x05, 0xD0, 0x01, 0x0B, 0x0B,
8144 ];
8145 let module = Module::decode(&bytes).unwrap();
8146 module.validate().unwrap();
8147 }
8148
8149 #[test]
8150 fn validate_typed_if_result_nullable_from_join_official_case() {
8151 let bytes = include_bytes!(
8152 "../../../baedeker-testdata/spec/valid/typed-if-result-nullable-from-join.wasm",
8153 );
8154 let module = Module::decode(bytes).unwrap();
8155 module.validate().unwrap();
8156 }
8157
8158 #[test]
8159 fn reject_typed_if_result_nullability_mismatch() {
8160 let bytes = include_bytes!(
8161 "../../../baedeker-testdata/spec/invalid-validate/typed-if-result-nullability-mismatch.wasm",
8162 );
8163 let module = Module::decode(bytes).unwrap();
8164 let err = module.validate().unwrap_err();
8165 assert_eq!(err.offset, ByteOffset(54));
8166 assert!(matches!(
8167 err.kind,
8168 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8169 if expected == vec![ValType::Ref(RefType::Typed {
8170 nullable: false,
8171 heap: crate::types::HeapType::Type(TypeIdx(0)),
8172 })] && found == vec![ValType::Ref(RefType::Typed {
8173 nullable: true,
8174 heap: crate::types::HeapType::Type(TypeIdx(0)),
8175 })]
8176 ));
8177 }
8178
8179 #[test]
8180 fn validate_typed_if_with_return_in_then_and_equivalent_signature() {
8181 let bytes = [
8182 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7f,
8183 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
8184 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x15, 0x02,
8185 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0e, 0x00, 0x20, 0x00, 0x04, 0x63, 0x01, 0xd2, 0x00,
8186 0x0f, 0x05, 0xd0, 0x01, 0x0b, 0x0b,
8187 ];
8188 let module = Module::decode(&bytes).unwrap();
8189 module.validate().unwrap();
8190 }
8191
8192 #[test]
8193 fn reject_typed_if_with_return_in_then_and_wrong_concrete_type() {
8194 let bytes = [
8195 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7e,
8196 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x63, 0x01, 0x03,
8197 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x15, 0x02,
8198 0x04, 0x00, 0x20, 0x00, 0x0b, 0x0e, 0x00, 0x20, 0x00, 0x04, 0x63, 0x01, 0xd2, 0x00,
8199 0x0f, 0x05, 0xd0, 0x01, 0x0b, 0x0b,
8200 ];
8201 let module = Module::decode(&bytes).unwrap();
8202 let err = module.validate().unwrap_err();
8203 assert_eq!(err.offset, ByteOffset(56));
8204 assert!(matches!(
8205 err.kind,
8206 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8207 if expected == vec![ValType::Ref(RefType::Typed {
8208 nullable: true,
8209 heap: crate::types::HeapType::Type(TypeIdx(1)),
8210 })] && found == vec![ValType::Ref(RefType::Typed {
8211 nullable: false,
8212 heap: crate::types::HeapType::Type(TypeIdx(0)),
8213 })]
8214 ));
8215 }
8216
8217 #[test]
8218 fn validate_typed_return_with_equivalent_signature() {
8219 let bytes = [
8220 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
8221 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8222 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x0e, 0x02, 0x04,
8223 0x00, 0x20, 0x00, 0x0b, 0x07, 0x00, 0xd2, 0x00, 0x0f, 0xd0, 0x01, 0x0b,
8224 ];
8225 let module = Module::decode(&bytes).unwrap();
8226 module.validate().unwrap();
8227 }
8228
8229 #[test]
8230 fn reject_typed_return_with_wrong_concrete_type() {
8231 let bytes = [
8232 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7e,
8233 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8234 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x0e, 0x02, 0x04,
8235 0x00, 0x20, 0x00, 0x0b, 0x07, 0x00, 0xd2, 0x00, 0x0f, 0xd0, 0x01, 0x0b,
8236 ];
8237 let module = Module::decode(&bytes).unwrap();
8238 let err = module.validate().unwrap_err();
8239 assert_eq!(err.offset, ByteOffset(50));
8240 assert!(matches!(
8241 err.kind,
8242 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8243 if expected == vec![ValType::Ref(RefType::Typed {
8244 nullable: true,
8245 heap: crate::types::HeapType::Type(TypeIdx(1)),
8246 })] && found == vec![ValType::Ref(RefType::Typed {
8247 nullable: false,
8248 heap: crate::types::HeapType::Type(TypeIdx(0)),
8249 })]
8250 ));
8251 }
8252
8253 #[test]
8254 fn validate_typed_loop_result_with_equivalent_signature() {
8255 let bytes = [
8256 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7f,
8257 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8258 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x0f, 0x02, 0x04,
8259 0x00, 0x20, 0x00, 0x0b, 0x08, 0x00, 0x03, 0x63, 0x01, 0xd2, 0x00, 0x0b, 0x0b,
8260 ];
8261 let module = Module::decode(&bytes).unwrap();
8262 module.validate().unwrap();
8263 }
8264
8265 #[test]
8266 fn validate_typed_loop_result_nullable_from_nonnull_official_case() {
8267 let bytes = include_bytes!(
8268 "../../../baedeker-testdata/spec/valid/typed-loop-result-nullable-from-nonnull.wasm",
8269 );
8270 let module = Module::decode(bytes).unwrap();
8271 module.validate().unwrap();
8272 }
8273
8274 #[test]
8275 fn reject_typed_loop_result_nullability_mismatch() {
8276 let bytes = include_bytes!(
8277 "../../../baedeker-testdata/spec/invalid-validate/typed-loop-result-nullability-mismatch.wasm",
8278 );
8279 let module = Module::decode(bytes).unwrap();
8280 let err = module.validate().unwrap_err();
8281 assert_eq!(err.offset, ByteOffset(35));
8282 assert!(matches!(
8283 err.kind,
8284 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8285 if expected == vec![ValType::Ref(RefType::Typed {
8286 nullable: false,
8287 heap: crate::types::HeapType::Type(TypeIdx(0)),
8288 })] && found == vec![ValType::Ref(RefType::Typed {
8289 nullable: true,
8290 heap: crate::types::HeapType::Type(TypeIdx(0)),
8291 })]
8292 ));
8293 }
8294
8295 #[test]
8296 fn reject_typed_loop_result_with_wrong_concrete_type() {
8297 let bytes = [
8298 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7e,
8299 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x63, 0x01, 0x03, 0x03,
8300 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0a, 0x0f, 0x02, 0x04,
8301 0x00, 0x20, 0x00, 0x0b, 0x08, 0x00, 0x03, 0x63, 0x01, 0xd2, 0x00, 0x0b, 0x0b,
8302 ];
8303 let module = Module::decode(&bytes).unwrap();
8304 let err = module.validate().unwrap_err();
8305 assert_eq!(err.offset, ByteOffset(53));
8306 assert!(matches!(
8307 err.kind,
8308 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8309 if expected == vec![ValType::Ref(RefType::Typed {
8310 nullable: true,
8311 heap: crate::types::HeapType::Type(TypeIdx(1)),
8312 })] && found == vec![ValType::Ref(RefType::Typed {
8313 nullable: false,
8314 heap: crate::types::HeapType::Type(TypeIdx(0)),
8315 })]
8316 ));
8317 }
8318
8319 #[test]
8320 fn validate_typed_return_if_nullable_official_case() {
8321 let bytes =
8322 include_bytes!("../../../baedeker-testdata/spec/valid/typed-return-if-nullable.wasm",);
8323 let module = Module::decode(bytes).unwrap();
8324 module.validate().unwrap();
8325 }
8326
8327 #[test]
8328 fn reject_typed_return_if_nullability_mismatch() {
8329 let bytes = include_bytes!(
8330 "../../../baedeker-testdata/spec/invalid-validate/typed-return-if-nullability-mismatch.wasm",
8331 );
8332 let module = Module::decode(bytes).unwrap();
8333 let err = module.validate().unwrap_err();
8334 assert_eq!(err.offset, ByteOffset(55));
8335 assert!(matches!(
8336 err.kind,
8337 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8338 if expected == vec![ValType::Ref(RefType::Typed {
8339 nullable: false,
8340 heap: crate::types::HeapType::Type(TypeIdx(0)),
8341 })] && found == vec![ValType::Ref(RefType::Typed {
8342 nullable: true,
8343 heap: crate::types::HeapType::Type(TypeIdx(0)),
8344 })]
8345 ));
8346 }
8347
8348 #[test]
8349 fn validate_typed_table_init_shared_source_to_return_nullable_official_case() {
8350 let bytes = include_bytes!(
8351 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-return-nullable.wasm",
8352 );
8353 let module = Module::decode(bytes).unwrap();
8354 module.validate().unwrap();
8355 }
8356
8357 #[test]
8358 fn reject_typed_table_init_shared_source_to_return_nullability_mismatch() {
8359 let bytes = include_bytes!(
8360 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-return-nullability-mismatch.wasm",
8361 );
8362 let module = Module::decode(bytes).unwrap();
8363 let err = module.validate().unwrap_err();
8364 assert_eq!(err.offset, ByteOffset(94));
8365 assert!(matches!(
8366 err.kind,
8367 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
8368 if expected == vec![ValType::Ref(RefType::Typed {
8369 nullable: false,
8370 heap: crate::types::HeapType::Type(TypeIdx(1)),
8371 })] && found == vec![ValType::Ref(RefType::Typed {
8372 nullable: true,
8373 heap: crate::types::HeapType::Type(TypeIdx(1)),
8374 })]
8375 ));
8376 }
8377
8378 #[test]
8379 fn validate_return_call_ref() {
8380 let bytes = [
8381 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7F,
8382 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00,
8383 0x0A, 0x0F, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x08, 0x00, 0x20, 0x00, 0xD2, 0x00,
8384 0x15, 0x00, 0x0B,
8385 ];
8386 let module = Module::decode(&bytes).unwrap();
8387 module.validate().unwrap();
8388 }
8389
8390 #[test]
8391 fn validate_return_call_ref_with_equivalent_concrete_type() {
8392 let bytes = [
8393 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
8394 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x00, 0x07, 0x05,
8395 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x0F, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x08,
8396 0x00, 0x20, 0x00, 0xD2, 0x00, 0x15, 0x01, 0x0B,
8397 ];
8398 let module = Module::decode(&bytes).unwrap();
8399 module.validate().unwrap();
8400 }
8401
8402 #[test]
8403 fn validate_typed_if_result_to_return_call_ref_with_equivalent_signature() {
8404 let bytes = include_bytes!(
8405 "../../../baedeker-testdata/spec/valid/typed-if-to-return-call-ref-equivalent-signature.wasm",
8406 );
8407 let module = Module::decode(bytes).unwrap();
8408 module.validate().unwrap();
8409 }
8410
8411 #[test]
8412 fn validate_return_call_ref_count_official_case() {
8413 let bytes =
8414 include_bytes!("../../../baedeker-testdata/spec/valid/return-call-ref-count.wasm");
8415 let module = Module::decode(bytes).unwrap();
8416 module.validate().unwrap();
8417 }
8418
8419 #[test]
8420 fn validate_typed_table_init_to_return_call_ref_result_nullable_official_case() {
8421 let bytes = include_bytes!(
8422 "../../../baedeker-testdata/spec/valid/typed-table-init-to-return-call-ref-result-nullable.wasm",
8423 );
8424 let module = Module::decode(bytes).unwrap();
8425 module.validate().unwrap();
8426 }
8427
8428 #[test]
8429 fn validate_typed_table_init_shared_source_to_return_call_ref_nullable_official_case() {
8430 let bytes = include_bytes!(
8431 "../../../baedeker-testdata/spec/valid/typed-table-init-shared-source-to-return-call-ref-nullable.wasm",
8432 );
8433 let module = Module::decode(bytes).unwrap();
8434 module.validate().unwrap();
8435 }
8436
8437 #[test]
8438 fn reject_typed_return_call_ref_result_wrong_concrete_type() {
8439 let bytes = include_bytes!(
8440 "../../../baedeker-testdata/spec/invalid-validate/typed-return-call-ref-result-wrong-concrete-type.wasm",
8441 );
8442 let module = Module::decode(bytes).unwrap();
8443 let err = module.validate().unwrap_err();
8444 assert_eq!(err.offset, ByteOffset(55));
8445 assert!(matches!(
8446 err.kind,
8447 ValidationErrorKind::ResultTypeMismatch { expected, found }
8448 if expected == vec![ValType::Ref(RefType::Typed {
8449 nullable: true,
8450 heap: crate::types::HeapType::Type(TypeIdx(1)),
8451 })] && found == vec![ValType::Ref(RefType::Typed {
8452 nullable: true,
8453 heap: crate::types::HeapType::Type(TypeIdx(0)),
8454 })]
8455 ));
8456 }
8457
8458 #[test]
8459 fn reject_typed_return_call_ref_result_nullability_mismatch() {
8460 let bytes = include_bytes!(
8461 "../../../baedeker-testdata/spec/invalid-validate/typed-return-call-ref-result-nullability-mismatch.wasm",
8462 );
8463 let module = Module::decode(bytes).unwrap();
8464 let err = module.validate().unwrap_err();
8465 assert_eq!(err.offset, ByteOffset(50));
8466 assert!(matches!(
8467 err.kind,
8468 ValidationErrorKind::ResultTypeMismatch { expected, found }
8469 if expected == vec![ValType::Ref(RefType::Typed {
8470 nullable: false,
8471 heap: crate::types::HeapType::Type(TypeIdx(0)),
8472 })] && found == vec![ValType::Ref(RefType::Typed {
8473 nullable: true,
8474 heap: crate::types::HeapType::Type(TypeIdx(0)),
8475 })]
8476 ));
8477 }
8478
8479 #[test]
8480 fn reject_typed_if_result_to_return_call_ref_with_wrong_concrete_type() {
8481 let bytes = include_bytes!(
8482 "../../../baedeker-testdata/spec/invalid-validate/typed-if-to-return-call-ref-wrong-concrete-type.wasm",
8483 );
8484 let module = Module::decode(bytes).unwrap();
8485 let err = module.validate().unwrap_err();
8486 assert_eq!(err.offset, ByteOffset(62));
8487 assert!(matches!(
8488 err.kind,
8489 ValidationErrorKind::TypeMismatch { op, expected, found }
8490 if op == "return_call_ref"
8491 && expected == ValType::Ref(RefType::Typed {
8492 nullable: true,
8493 heap: crate::types::HeapType::Type(TypeIdx(1)),
8494 })
8495 && found == ValType::Ref(RefType::Typed {
8496 nullable: true,
8497 heap: crate::types::HeapType::Type(TypeIdx(0)),
8498 })
8499 ));
8500 }
8501
8502 #[test]
8503 fn reject_typed_table_init_to_return_call_ref_result_nullability_mismatch() {
8504 let bytes = include_bytes!(
8505 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-to-return-call-ref-result-nullability-mismatch.wasm",
8506 );
8507 let module = Module::decode(bytes).unwrap();
8508 let err = module.validate().unwrap_err();
8509 assert_eq!(err.offset, ByteOffset(98));
8510 assert!(matches!(
8511 err.kind,
8512 ValidationErrorKind::ResultTypeMismatch { expected, found }
8513 if expected == vec![ValType::Ref(RefType::Typed {
8514 nullable: false,
8515 heap: crate::types::HeapType::Type(TypeIdx(0)),
8516 })] && found == vec![ValType::Ref(RefType::Typed {
8517 nullable: true,
8518 heap: crate::types::HeapType::Type(TypeIdx(0)),
8519 })]
8520 ));
8521 }
8522
8523 #[test]
8524 fn reject_typed_table_init_shared_source_to_return_call_ref_nullability_mismatch() {
8525 let bytes = include_bytes!(
8526 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-return-call-ref-nullability-mismatch.wasm",
8527 );
8528 let module = Module::decode(bytes).unwrap();
8529 let err = module.validate().unwrap_err();
8530 assert_eq!(err.offset, ByteOffset(94));
8531 assert!(matches!(
8532 err.kind,
8533 ValidationErrorKind::ResultTypeMismatch { expected, found }
8534 if expected == vec![ValType::Ref(RefType::Typed {
8535 nullable: false,
8536 heap: crate::types::HeapType::Type(TypeIdx(0)),
8537 })] && found == vec![ValType::Ref(RefType::Typed {
8538 nullable: true,
8539 heap: crate::types::HeapType::Type(TypeIdx(0)),
8540 })]
8541 ));
8542 }
8543
8544 #[test]
8545 fn reject_call_ref_with_non_funcref_reference() {
8546 let bytes = [
8547 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
8548 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0xD0, 0x6F, 0x14, 0x00,
8549 0x0B,
8550 ];
8551 let module = Module::decode(&bytes).unwrap();
8552 let err = module.validate().unwrap_err();
8553 assert_eq!(err.offset, ByteOffset(26));
8554 assert!(matches!(
8555 err.kind,
8556 ValidationErrorKind::TypeMismatch {
8557 op: "call_ref",
8558 expected: ValType::Ref(RefType::Typed {
8559 nullable: true,
8560 heap: crate::types::HeapType::Type(TypeIdx(0)),
8561 }),
8562 found: ValType::Ref(RefType::ExternRef),
8563 }
8564 ));
8565 }
8566
8567 #[test]
8568 fn reject_call_ref_non_funcref_externref_official_case() {
8569 let bytes = include_bytes!(
8570 "../../../baedeker-testdata/spec/invalid-validate/call-ref-non-funcref-externref.wasm",
8571 );
8572 let module = Module::decode(bytes).unwrap();
8573 let err = module.validate().unwrap_err();
8574 assert_eq!(err.offset, ByteOffset(29));
8575 assert!(matches!(
8576 err.kind,
8577 ValidationErrorKind::TypeMismatch { op, expected, found }
8578 if op == "call_ref"
8579 && expected == ValType::Ref(RefType::Typed {
8580 nullable: true,
8581 heap: crate::types::HeapType::Type(TypeIdx(0)),
8582 })
8583 && found == ValType::Ref(RefType::ExternRef)
8584 ));
8585 }
8586
8587 #[test]
8588 fn reject_call_ref_non_funcref_funcref_official_case() {
8589 let bytes = include_bytes!(
8590 "../../../baedeker-testdata/spec/invalid-validate/call-ref-non-funcref-funcref.wasm",
8591 );
8592 let module = Module::decode(bytes).unwrap();
8593 let err = module.validate().unwrap_err();
8594 assert_eq!(err.offset, ByteOffset(29));
8595 assert!(matches!(
8596 err.kind,
8597 ValidationErrorKind::TypeMismatch { op, expected, found }
8598 if op == "call_ref"
8599 && expected == ValType::Ref(RefType::Typed {
8600 nullable: true,
8601 heap: crate::types::HeapType::Type(TypeIdx(0)),
8602 })
8603 && found == ValType::Ref(RefType::FuncRef)
8604 ));
8605 }
8606
8607 #[test]
8608 fn reject_return_call_ref_non_funcref_externref_official_case() {
8609 let bytes = include_bytes!(
8610 "../../../baedeker-testdata/spec/invalid-validate/return-call-ref-non-funcref-externref.wasm",
8611 );
8612 let module = Module::decode(bytes).unwrap();
8613 let err = module.validate().unwrap_err();
8614 assert_eq!(err.offset, ByteOffset(29));
8615 assert!(matches!(
8616 err.kind,
8617 ValidationErrorKind::TypeMismatch { op, expected, found }
8618 if op == "return_call_ref"
8619 && expected == ValType::Ref(RefType::Typed {
8620 nullable: true,
8621 heap: crate::types::HeapType::Type(TypeIdx(0)),
8622 })
8623 && found == ValType::Ref(RefType::ExternRef)
8624 ));
8625 }
8626
8627 #[test]
8628 fn reject_return_call_ref_non_funcref_funcref_official_case() {
8629 let bytes = include_bytes!(
8630 "../../../baedeker-testdata/spec/invalid-validate/return-call-ref-non-funcref-funcref.wasm",
8631 );
8632 let module = Module::decode(bytes).unwrap();
8633 let err = module.validate().unwrap_err();
8634 assert_eq!(err.offset, ByteOffset(29));
8635 assert!(matches!(
8636 err.kind,
8637 ValidationErrorKind::TypeMismatch { op, expected, found }
8638 if op == "return_call_ref"
8639 && expected == ValType::Ref(RefType::Typed {
8640 nullable: true,
8641 heap: crate::types::HeapType::Type(TypeIdx(0)),
8642 })
8643 && found == ValType::Ref(RefType::FuncRef)
8644 ));
8645 }
8646
8647 #[test]
8648 fn reject_return_call_ref_multi_result_official_case() {
8649 let bytes = include_bytes!(
8650 "../../../baedeker-testdata/spec/invalid-validate/return-call-ref-multi-result.wasm",
8651 );
8652 let module = Module::decode(bytes).unwrap();
8653 let err = module.validate().unwrap_err();
8654 assert_eq!(err.offset, ByteOffset(33));
8655 assert!(matches!(
8656 err.kind,
8657 ValidationErrorKind::ResultTypeMismatch { expected, found }
8658 if expected == vec![ValType::Num(crate::types::NumType::I32)]
8659 && found == vec![
8660 ValType::Num(crate::types::NumType::I32),
8661 ValType::Num(crate::types::NumType::I32),
8662 ]
8663 ));
8664 }
8665
8666 #[test]
8667 fn reject_return_call_ref_result_mismatch() {
8668 let bytes = [
8669 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, 0x00, 0x01,
8670 0x7E, 0x60, 0x00, 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x01, 0x07, 0x05, 0x01, 0x01,
8671 0x66, 0x00, 0x00, 0x0A, 0x0D, 0x02, 0x04, 0x00, 0x42, 0x00, 0x0B, 0x06, 0x00, 0xD2,
8672 0x00, 0x15, 0x00, 0x0B,
8673 ];
8674 let module = Module::decode(&bytes).unwrap();
8675 let err = module.validate().unwrap_err();
8676 assert_eq!(err.offset, ByteOffset(43));
8677 assert!(matches!(
8678 err.kind,
8679 ValidationErrorKind::ResultTypeMismatch {
8680 expected,
8681 found,
8682 } if expected == vec![ValType::Num(crate::types::NumType::I32)]
8683 && found == vec![ValType::Num(crate::types::NumType::I64)]
8684 ));
8685 }
8686
8687 #[test]
8688 fn reject_call_ref_with_wrong_concrete_type() {
8689 let bytes = [
8690 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
8691 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7F, 0x03, 0x03, 0x02, 0x00, 0x01, 0x07, 0x05,
8692 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x0F, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x08,
8693 0x00, 0x42, 0x00, 0xD2, 0x00, 0x14, 0x01, 0x0B,
8694 ];
8695 let module = Module::decode(&bytes).unwrap();
8696 let err = module.validate().unwrap_err();
8697 assert_eq!(err.offset, ByteOffset(47));
8698 assert!(matches!(
8699 err.kind,
8700 ValidationErrorKind::TypeMismatch {
8701 op: "call_ref",
8702 expected: ValType::Ref(RefType::Typed {
8703 nullable: true,
8704 heap: crate::types::HeapType::Type(TypeIdx(1)),
8705 }),
8706 found: ValType::Ref(RefType::Typed {
8707 nullable: false,
8708 heap: crate::types::HeapType::Type(TypeIdx(0)),
8709 }),
8710 }
8711 ));
8712 }
8713
8714 #[test]
8715 fn reject_typed_ref_global_init_from_imported_typed_global_with_wrong_concrete_type() {
8716 let bytes = [
8717 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
8718 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x02, 0x0B, 0x01, 0x03, 0x65, 0x6E, 0x76,
8719 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x06, 0x07, 0x01, 0x63, 0x01, 0x00, 0x23, 0x00,
8720 0x0B,
8721 ];
8722 let module = Module::decode(&bytes).unwrap();
8723 let err = module.validate().unwrap_err();
8724 assert_eq!(err.offset, ByteOffset(40));
8725 assert!(matches!(
8726 err.kind,
8727 ValidationErrorKind::GlobalInitTypeMismatch {
8728 expected: ValType::Ref(RefType::Typed {
8729 nullable: true,
8730 heap: crate::types::HeapType::Type(TypeIdx(1)),
8731 }),
8732 found: ValType::Ref(RefType::Typed {
8733 nullable: true,
8734 heap: crate::types::HeapType::Type(TypeIdx(0)),
8735 }),
8736 }
8737 ));
8738 }
8739
8740 #[test]
8741 fn reject_typed_table_get_to_defined_mut_global_with_wrong_concrete_type() {
8742 let bytes = include_bytes!(
8743 "../../../baedeker-testdata/spec/invalid-validate/typed-table-to-defined-mut-global-wrong-concrete-type.wasm",
8744 );
8745 let module = Module::decode(bytes).unwrap();
8746 let err = module.validate().unwrap_err();
8747 assert_eq!(err.offset, ByteOffset(74));
8748 assert!(matches!(
8749 err.kind,
8750 ValidationErrorKind::TypeMismatch { op, expected, found }
8751 if op == "global.set"
8752 && expected == ValType::Ref(RefType::Typed {
8753 nullable: true,
8754 heap: crate::types::HeapType::Type(TypeIdx(1)),
8755 })
8756 && found == ValType::Ref(RefType::Typed {
8757 nullable: true,
8758 heap: crate::types::HeapType::Type(TypeIdx(0)),
8759 })
8760 ));
8761 }
8762
8763 #[test]
8764 fn reject_imported_typed_table_get_to_defined_mut_global_with_wrong_concrete_type() {
8765 let bytes = include_bytes!(
8766 "../../../baedeker-testdata/spec/invalid-validate/imported-typed-table-to-defined-mut-global-wrong-concrete-type.wasm",
8767 );
8768 let module = Module::decode(bytes).unwrap();
8769 let err = module.validate().unwrap_err();
8770 assert_eq!(err.offset, ByteOffset(62));
8771 assert!(matches!(
8772 err.kind,
8773 ValidationErrorKind::TypeMismatch { op, expected, found }
8774 if op == "global.set"
8775 && expected == ValType::Ref(RefType::Typed {
8776 nullable: true,
8777 heap: crate::types::HeapType::Type(TypeIdx(1)),
8778 })
8779 && found == ValType::Ref(RefType::Typed {
8780 nullable: true,
8781 heap: crate::types::HeapType::Type(TypeIdx(0)),
8782 })
8783 ));
8784 }
8785
8786 #[test]
8787 fn reject_typed_local_set_if_nullability_mismatch() {
8788 let bytes = include_bytes!(
8789 "../../../baedeker-testdata/spec/invalid-validate/typed-local-set-if-nullability-mismatch.wasm",
8790 );
8791 let module = Module::decode(bytes).unwrap();
8792 let err = module.validate().unwrap_err();
8793 assert_eq!(err.offset, ByteOffset(56));
8794 assert!(matches!(
8795 err.kind,
8796 ValidationErrorKind::TypeMismatch { op, expected, found }
8797 if op == "local.set"
8798 && expected == ValType::Ref(RefType::Typed {
8799 nullable: false,
8800 heap: crate::types::HeapType::Type(TypeIdx(0)),
8801 })
8802 && found == ValType::Ref(RefType::Typed {
8803 nullable: true,
8804 heap: crate::types::HeapType::Type(TypeIdx(0)),
8805 })
8806 ));
8807 }
8808
8809 #[test]
8810 fn reject_typed_local_if_to_return_nullability_mismatch() {
8811 let bytes = include_bytes!(
8812 "../../../baedeker-testdata/spec/invalid-validate/typed-local-if-to-return-nullability-mismatch.wasm",
8813 );
8814 let module = Module::decode(bytes).unwrap();
8815 let err = module.validate().unwrap_err();
8816 assert_eq!(err.offset, ByteOffset(62));
8817 assert!(matches!(
8818 err.kind,
8819 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
8820 if expected == vec![ValType::Ref(RefType::Typed {
8821 nullable: false,
8822 heap: crate::types::HeapType::Type(TypeIdx(0)),
8823 })] && found == vec![ValType::Ref(RefType::Typed {
8824 nullable: true,
8825 heap: crate::types::HeapType::Type(TypeIdx(0)),
8826 })]
8827 ));
8828 }
8829
8830 #[test]
8831 fn reject_typed_global_set_if_nullability_mismatch() {
8832 let bytes = include_bytes!(
8833 "../../../baedeker-testdata/spec/invalid-validate/typed-global-set-if-nullability-mismatch.wasm",
8834 );
8835 let module = Module::decode(bytes).unwrap();
8836 let err = module.validate().unwrap_err();
8837 assert_eq!(err.offset, ByteOffset(62));
8838 assert!(matches!(
8839 err.kind,
8840 ValidationErrorKind::TypeMismatch { op, expected, found }
8841 if op == "global.set"
8842 && expected == ValType::Ref(RefType::Typed {
8843 nullable: false,
8844 heap: crate::types::HeapType::Type(TypeIdx(0)),
8845 })
8846 && found == ValType::Ref(RefType::Typed {
8847 nullable: true,
8848 heap: crate::types::HeapType::Type(TypeIdx(0)),
8849 })
8850 ));
8851 }
8852
8853 #[test]
8854 fn reject_typed_table_init_shared_source_to_global_set_nullability_mismatch() {
8855 let bytes = include_bytes!(
8856 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-shared-source-to-global-set-nullability-mismatch.wasm",
8857 );
8858 let module = Module::decode(bytes).unwrap();
8859 let err = module.validate().unwrap_err();
8860 assert_eq!(err.offset, ByteOffset(98));
8861 assert!(matches!(
8862 err.kind,
8863 ValidationErrorKind::TypeMismatch { op, expected, found }
8864 if op == "global.set"
8865 && expected == ValType::Ref(RefType::Typed {
8866 nullable: false,
8867 heap: crate::types::HeapType::Type(TypeIdx(1)),
8868 })
8869 && found == ValType::Ref(RefType::Typed {
8870 nullable: true,
8871 heap: crate::types::HeapType::Type(TypeIdx(1)),
8872 })
8873 ));
8874 }
8875
8876 #[test]
8877 fn reject_typed_global_if_to_return_nullability_mismatch() {
8878 let bytes = include_bytes!(
8879 "../../../baedeker-testdata/spec/invalid-validate/typed-global-if-to-return-nullability-mismatch.wasm",
8880 );
8881 let module = Module::decode(bytes).unwrap();
8882 let err = module.validate().unwrap_err();
8883 assert_eq!(err.offset, ByteOffset(68));
8884 assert!(matches!(
8885 err.kind,
8886 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
8887 if expected == vec![ValType::Ref(RefType::Typed {
8888 nullable: false,
8889 heap: crate::types::HeapType::Type(TypeIdx(0)),
8890 })] && found == vec![ValType::Ref(RefType::Typed {
8891 nullable: true,
8892 heap: crate::types::HeapType::Type(TypeIdx(0)),
8893 })]
8894 ));
8895 }
8896
8897 #[test]
8898 fn reject_typed_table_set_if_nullability_mismatch() {
8899 let bytes = include_bytes!(
8900 "../../../baedeker-testdata/spec/invalid-validate/typed-table-set-if-nullability-mismatch.wasm",
8901 );
8902 let module = Module::decode(bytes).unwrap();
8903 let err = module.validate().unwrap_err();
8904 assert_eq!(err.offset, ByteOffset(67));
8905 assert!(matches!(
8906 err.kind,
8907 ValidationErrorKind::TypeMismatch { op, expected, found }
8908 if op == "table.set"
8909 && expected == ValType::Ref(RefType::Typed {
8910 nullable: false,
8911 heap: crate::types::HeapType::Type(TypeIdx(0)),
8912 })
8913 && found == ValType::Ref(RefType::Typed {
8914 nullable: true,
8915 heap: crate::types::HeapType::Type(TypeIdx(0)),
8916 })
8917 ));
8918 }
8919
8920 #[test]
8921 fn reject_typed_table_if_to_return_nullability_mismatch() {
8922 let bytes = include_bytes!(
8923 "../../../baedeker-testdata/spec/invalid-validate/typed-table-if-to-return-nullability-mismatch.wasm",
8924 );
8925 let module = Module::decode(bytes).unwrap();
8926 let err = module.validate().unwrap_err();
8927 assert_eq!(err.offset, ByteOffset(70));
8928 assert!(matches!(
8929 err.kind,
8930 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
8931 if expected == vec![ValType::Ref(RefType::Typed {
8932 nullable: false,
8933 heap: crate::types::HeapType::Type(TypeIdx(0)),
8934 })] && found == vec![ValType::Ref(RefType::Typed {
8935 nullable: true,
8936 heap: crate::types::HeapType::Type(TypeIdx(0)),
8937 })]
8938 ));
8939 }
8940
8941 #[test]
8942 fn reject_typed_passive_element_nullability_mismatch() {
8943 let bytes = include_bytes!(
8944 "../../../baedeker-testdata/spec/invalid-validate/typed-passive-element-nullability-mismatch.wasm",
8945 );
8946 let module = Module::decode(bytes).unwrap();
8947 let err = module.validate().unwrap_err();
8948 assert_eq!(err.offset, ByteOffset(32));
8949 assert!(matches!(
8950 err.kind,
8951 ValidationErrorKind::ElementExprTypeMismatch { expected, found }
8952 if expected == ValType::Ref(RefType::Typed {
8953 nullable: false,
8954 heap: crate::types::HeapType::Type(TypeIdx(0)),
8955 })
8956 && found == ValType::Ref(RefType::Typed {
8957 nullable: true,
8958 heap: crate::types::HeapType::Type(TypeIdx(0)),
8959 })
8960 ));
8961 }
8962
8963 #[test]
8964 fn reject_typed_table_init_nullability_mismatch() {
8965 let bytes = include_bytes!(
8966 "../../../baedeker-testdata/spec/invalid-validate/typed-table-init-nullability-mismatch.wasm",
8967 );
8968 let module = Module::decode(bytes).unwrap();
8969 let err = module.validate().unwrap_err();
8970 assert_eq!(err.offset, ByteOffset(76));
8971 assert!(matches!(
8972 err.kind,
8973 ValidationErrorKind::ElementTableTypeMismatch { expected, found }
8974 if expected == RefType::Typed {
8975 nullable: false,
8976 heap: crate::types::HeapType::Type(TypeIdx(0)),
8977 }
8978 && found == RefType::Typed {
8979 nullable: true,
8980 heap: crate::types::HeapType::Type(TypeIdx(0)),
8981 }
8982 ));
8983 }
8984
8985 #[test]
8986 fn reject_typed_defined_global_passive_element_table_init_to_return_nullability_mismatch() {
8987 let bytes = include_bytes!(
8988 "../../../baedeker-testdata/spec/invalid-validate/typed-defined-global-passive-element-table-init-to-return-nullability-mismatch.wasm",
8989 );
8990 let module = Module::decode(bytes).unwrap();
8991 let err = module.validate().unwrap_err();
8992 assert_eq!(err.offset, ByteOffset(83));
8993 assert!(matches!(
8994 err.kind,
8995 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
8996 if expected == vec![ValType::Ref(RefType::Typed {
8997 nullable: false,
8998 heap: crate::types::HeapType::Type(TypeIdx(0)),
8999 })] && found == vec![ValType::Ref(RefType::Typed {
9000 nullable: true,
9001 heap: crate::types::HeapType::Type(TypeIdx(0)),
9002 })]
9003 ));
9004 }
9005
9006 #[test]
9007 fn reject_typed_imported_global_passive_element_table_init_to_return_nullability_mismatch() {
9008 let bytes = include_bytes!(
9009 "../../../baedeker-testdata/spec/invalid-validate/typed-imported-global-passive-element-table-init-to-return-nullability-mismatch.wasm",
9010 );
9011 let module = Module::decode(bytes).unwrap();
9012 let err = module.validate().unwrap_err();
9013 assert_eq!(err.offset, ByteOffset(74));
9014 assert!(matches!(
9015 err.kind,
9016 ValidationErrorKind::FunctionResultTypeMismatch { expected, found, .. }
9017 if expected == vec![ValType::Ref(RefType::Typed {
9018 nullable: false,
9019 heap: crate::types::HeapType::Type(TypeIdx(0)),
9020 })] && found == vec![ValType::Ref(RefType::Typed {
9021 nullable: true,
9022 heap: crate::types::HeapType::Type(TypeIdx(0)),
9023 })]
9024 ));
9025 }
9026
9027 #[test]
9028 fn reject_typed_defined_global_passive_element_table_init_to_global_set_nullability_mismatch() {
9029 let bytes = include_bytes!(
9030 "../../../baedeker-testdata/spec/invalid-validate/typed-defined-global-passive-element-table-init-to-global-set-nullability-mismatch.wasm",
9031 );
9032 let module = Module::decode(bytes).unwrap();
9033 let err = module.validate().unwrap_err();
9034 assert_eq!(err.offset, ByteOffset(87));
9035 assert!(matches!(
9036 err.kind,
9037 ValidationErrorKind::TypeMismatch { op, expected, found }
9038 if op == "global.set"
9039 && expected == ValType::Ref(RefType::Typed {
9040 nullable: false,
9041 heap: crate::types::HeapType::Type(TypeIdx(0)),
9042 })
9043 && found == ValType::Ref(RefType::Typed {
9044 nullable: true,
9045 heap: crate::types::HeapType::Type(TypeIdx(0)),
9046 })
9047 ));
9048 }
9049
9050 #[test]
9051 fn reject_typed_imported_global_passive_element_table_init_nullability_mismatch() {
9052 let bytes = include_bytes!(
9053 "../../../baedeker-testdata/spec/invalid-validate/typed-imported-global-passive-element-table-init-nullability-mismatch.wasm",
9054 );
9055 let module = Module::decode(bytes).unwrap();
9056 let err = module.validate().unwrap_err();
9057 assert_eq!(err.offset, ByteOffset(79));
9058 assert!(matches!(
9062 err.kind,
9063 ValidationErrorKind::ElementTableTypeMismatch { expected, found }
9064 if expected == RefType::Typed {
9065 nullable: false,
9066 heap: crate::types::HeapType::Type(TypeIdx(1)),
9067 }
9068 && found == RefType::Typed {
9069 nullable: true,
9070 heap: crate::types::HeapType::Type(TypeIdx(0)),
9071 }
9072 ));
9073 }
9074
9075 #[test]
9076 fn reject_typed_element_expr_from_imported_typed_global_with_wrong_concrete_type() {
9077 let bytes = [
9078 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x60, 0x01, 0x7F,
9079 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x02, 0x0B, 0x01, 0x03, 0x65, 0x6E, 0x76,
9080 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x01, 0x09,
9081 0x0C, 0x01, 0x06, 0x00, 0x41, 0x00, 0x0B, 0x63, 0x01, 0x01, 0x23, 0x00, 0x0B,
9082 ];
9083 let module = Module::decode(&bytes).unwrap();
9084 let err = module.validate().unwrap_err();
9085 assert_eq!(err.offset, ByteOffset(52));
9086 assert!(matches!(
9087 err.kind,
9088 ValidationErrorKind::ElementExprTypeMismatch {
9089 expected: ValType::Ref(RefType::Typed {
9090 nullable: true,
9091 heap: crate::types::HeapType::Type(TypeIdx(1)),
9092 }),
9093 found: ValType::Ref(RefType::Typed {
9094 nullable: true,
9095 heap: crate::types::HeapType::Type(TypeIdx(0)),
9096 }),
9097 }
9098 ));
9099 }
9100
9101 #[test]
9102 fn reject_imported_typed_global_to_imported_table_with_wrong_concrete_type() {
9103 let bytes = [
9104 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, 0x01, 0x7F,
9105 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x60, 0x00, 0x01, 0x63, 0x01, 0x02, 0x16,
9106 0x02, 0x03, 0x65, 0x6E, 0x76, 0x01, 0x67, 0x03, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E,
9107 0x76, 0x01, 0x74, 0x01, 0x63, 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x02, 0x0A, 0x0E,
9108 0x01, 0x0C, 0x00, 0x41, 0x00, 0x23, 0x00, 0x26, 0x00, 0x41, 0x00, 0x25, 0x00, 0x0B,
9109 ];
9110 let module = Module::decode(&bytes).unwrap();
9111 let err = module.validate().unwrap_err();
9112 assert_eq!(err.offset, ByteOffset(63));
9113 assert!(matches!(
9114 err.kind,
9115 ValidationErrorKind::TypeMismatch {
9116 op: "table.set",
9117 expected: ValType::Ref(RefType::Typed {
9118 nullable: true,
9119 heap: crate::types::HeapType::Type(TypeIdx(1)),
9120 }),
9121 found: ValType::Ref(RefType::Typed {
9122 nullable: true,
9123 heap: crate::types::HeapType::Type(TypeIdx(0)),
9124 }),
9125 }
9126 ));
9127 }
9128
9129 #[test]
9130 fn reject_typed_passive_element_from_defined_typed_global_with_wrong_concrete_type() {
9131 let bytes = include_bytes!(
9132 "../../../baedeker-testdata/spec/invalid-validate/defined-typed-global-passive-element-wrong-concrete-type.wasm",
9133 );
9134 let module = Module::decode(bytes).unwrap();
9135 let err = module.validate().unwrap_err();
9136 assert_eq!(err.offset, ByteOffset(48));
9137 assert!(matches!(
9138 err.kind,
9139 ValidationErrorKind::ElementExprTypeMismatch { expected, found }
9140 if expected == ValType::Ref(RefType::Typed {
9141 nullable: true,
9142 heap: crate::types::HeapType::Type(TypeIdx(1)),
9143 })
9144 && found == ValType::Ref(RefType::Typed {
9145 nullable: true,
9146 heap: crate::types::HeapType::Type(TypeIdx(0)),
9147 })
9148 ));
9149 }
9150
9151 #[test]
9152 fn reject_typed_passive_element_from_imported_typed_global_with_wrong_concrete_type() {
9153 let bytes = include_bytes!(
9154 "../../../baedeker-testdata/spec/invalid-validate/imported-typed-global-passive-element-wrong-concrete-type.wasm",
9155 );
9156 let module = Module::decode(bytes).unwrap();
9157 let err = module.validate().unwrap_err();
9158 assert_eq!(err.offset, ByteOffset(41));
9159 assert!(matches!(
9160 err.kind,
9161 ValidationErrorKind::ElementExprTypeMismatch { expected, found }
9162 if expected == ValType::Ref(RefType::Typed {
9163 nullable: true,
9164 heap: crate::types::HeapType::Type(TypeIdx(1)),
9165 })
9166 && found == ValType::Ref(RefType::Typed {
9167 nullable: true,
9168 heap: crate::types::HeapType::Type(TypeIdx(0)),
9169 })
9170 ));
9171 }
9172
9173 #[test]
9174 fn reject_typed_if_result_with_wrong_concrete_type() {
9175 let bytes = [
9176 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x03, 0x60, 0x01, 0x7F,
9177 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x60, 0x01, 0x7F, 0x01, 0x63, 0x01, 0x03,
9178 0x03, 0x02, 0x00, 0x02, 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, 0x0A, 0x14, 0x02,
9179 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0D, 0x00, 0x20, 0x00, 0x04, 0x63, 0x01, 0xD2, 0x00,
9180 0x05, 0xD0, 0x01, 0x0B, 0x0B,
9181 ];
9182 let module = Module::decode(&bytes).unwrap();
9183 let err = module.validate().unwrap_err();
9184 assert_eq!(err.offset, ByteOffset(56));
9185 assert!(matches!(
9186 err.kind,
9187 ValidationErrorKind::ControlResultTypeMismatch { expected, found }
9188 if expected == vec![ValType::Ref(RefType::Typed {
9189 nullable: true,
9190 heap: crate::types::HeapType::Type(TypeIdx(1)),
9191 })] && found == vec![ValType::Ref(RefType::Typed {
9192 nullable: false,
9193 heap: crate::types::HeapType::Type(TypeIdx(0)),
9194 })]
9195 ));
9196 }
9197
9198 #[test]
9199 fn reject_table_init_with_incompatible_typed_element_segment() {
9200 let bytes = [
9201 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x03, 0x60, 0x01, 0x7F,
9202 0x01, 0x7F, 0x60, 0x01, 0x7E, 0x01, 0x7E, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00,
9203 0x02, 0x04, 0x05, 0x01, 0x63, 0x01, 0x00, 0x04, 0x07, 0x0C, 0x02, 0x01, 0x66, 0x00,
9204 0x00, 0x04, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x01, 0x09, 0x08, 0x01, 0x05, 0x63, 0x00,
9205 0x01, 0xD2, 0x00, 0x0B, 0x0A, 0x13, 0x02, 0x04, 0x00, 0x20, 0x00, 0x0B, 0x0C, 0x00,
9206 0x41, 0x00, 0x41, 0x00, 0x41, 0x01, 0xFC, 0x0C, 0x00, 0x00, 0x0B,
9207 ];
9208 let module = Module::decode(&bytes).unwrap();
9209 let err = module.validate().unwrap_err();
9210 assert_eq!(err.offset, ByteOffset(76));
9211 assert!(matches!(
9212 err.kind,
9213 ValidationErrorKind::ElementTableTypeMismatch {
9214 expected: RefType::Typed {
9215 nullable: true,
9216 heap: crate::types::HeapType::Type(TypeIdx(1)),
9217 },
9218 found: RefType::Typed {
9219 nullable: true,
9220 heap: crate::types::HeapType::Type(TypeIdx(0)),
9221 },
9222 }
9223 ));
9224 }
9225
9226 #[test]
9227 fn reject_return_call_indirect_result_mismatch() {
9228 let bytes = [
9229 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, 0x00, 0x01,
9230 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x03, 0x02, 0x01, 0x00, 0x04, 0x04, 0x01, 0x70, 0x00,
9231 0x01, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x41, 0x00, 0x13, 0x01, 0x00, 0x0B,
9232 ];
9233 let module = Module::decode(&bytes).unwrap();
9234 let err = module.validate().unwrap_err();
9235 assert_eq!(err.offset, ByteOffset(36));
9236 assert!(matches!(
9237 err.kind,
9238 ValidationErrorKind::ResultTypeMismatch {
9239 expected,
9240 found,
9241 } if expected == vec![ValType::Num(crate::types::NumType::I32)]
9242 && found == vec![ValType::Num(crate::types::NumType::I64)]
9243 ));
9244 }
9245
9246 #[test]
9247 fn reject_call_indirect_with_non_funcref_table() {
9248 let bytes = [
9249 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
9250 0x02, 0x0D, 0x01, 0x03, b'e', b'n', b'v', 0x03, b't', b'a', b'b', 0x01, 0x6F, 0x00,
9251 0x01, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x09, 0x01, 0x07, 0x00, 0x41, 0x00, 0x11, 0x00,
9252 0x00, 0x0B,
9253 ];
9254 let module = Module::decode(&bytes).unwrap();
9255 let err = module.validate().unwrap_err();
9256 assert!(matches!(
9257 err.kind,
9258 ValidationErrorKind::InvalidCallIndirectTableType {
9259 expected: RefType::FuncRef,
9260 found: RefType::ExternRef,
9261 }
9262 ));
9263 }
9264
9265 #[test]
9266 fn reject_return_call_indirect_with_non_funcref_table() {
9267 let bytes = [
9268 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
9269 0x7F, 0x03, 0x02, 0x01, 0x00, 0x04, 0x04, 0x01, 0x6F, 0x00, 0x01, 0x0A, 0x09, 0x01,
9270 0x07, 0x00, 0x41, 0x00, 0x13, 0x00, 0x00, 0x0B,
9271 ];
9272 let module = Module::decode(&bytes).unwrap();
9273 let err = module.validate().unwrap_err();
9274 assert_eq!(err.offset, ByteOffset(32));
9275 assert!(matches!(
9276 err.kind,
9277 ValidationErrorKind::InvalidCallIndirectTableType {
9278 expected: RefType::FuncRef,
9279 found: RefType::ExternRef,
9280 }
9281 ));
9282 }
9283
9284 #[test]
9285 fn validate_table_get_set_size_and_grow() {
9286 let bytes = [
9287 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x01,
9288 0x7F, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x04, 0x01, 0x70, 0x00,
9289 0x01, 0x0A, 0x1D, 0x02, 0x0A, 0x00, 0x41, 0x00, 0x25, 0x00, 0x1A, 0xFC, 0x10, 0x00,
9290 0x0B, 0x10, 0x00, 0x41, 0x00, 0xD0, 0x70, 0x26, 0x00, 0xD0, 0x70, 0x41, 0x01, 0xFC,
9291 0x0F, 0x00, 0x1A, 0x0B,
9292 ];
9293 let module = Module::decode(&bytes).unwrap();
9294 module.validate().unwrap();
9295 }
9296
9297 #[test]
9298 fn validate_table_get_set_size_and_grow_on_nonzero_table() {
9299 let bytes = [
9300 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x01,
9301 0x7F, 0x60, 0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x07, 0x02, 0x70, 0x00,
9302 0x01, 0x70, 0x00, 0x01, 0x0A, 0x1D, 0x02, 0x0A, 0x00, 0x41, 0x00, 0x25, 0x01, 0x1A,
9303 0xFC, 0x10, 0x01, 0x0B, 0x10, 0x00, 0x41, 0x00, 0xD0, 0x70, 0x26, 0x01, 0xD0, 0x70,
9304 0x41, 0x01, 0xFC, 0x0F, 0x01, 0x1A, 0x0B,
9305 ];
9306 let module = Module::decode(&bytes).unwrap();
9307 module.validate().unwrap();
9308 }
9309
9310 #[test]
9311 fn validate_broader_numeric_operators() {
9312 let bytes = [
9313 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 0x00, 0x01,
9314 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x60, 0x00, 0x01, 0x7D, 0x60, 0x00, 0x01, 0x7C, 0x03,
9315 0x05, 0x04, 0x00, 0x01, 0x02, 0x03, 0x0A, 0x26, 0x04, 0x08, 0x00, 0x41, 0x03, 0x41,
9316 0x01, 0x6B, 0x45, 0x0B, 0x05, 0x00, 0x42, 0x05, 0x79, 0x0B, 0x08, 0x00, 0x43, 0x00,
9317 0x00, 0x80, 0x3F, 0x8B, 0x0B, 0x0C, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9318 0xF0, 0x3F, 0x99, 0x0B,
9319 ];
9320 let module = Module::decode(&bytes).unwrap();
9321 module.validate().unwrap();
9322 }
9323
9324 #[test]
9325 fn reject_broader_numeric_operator_type_mismatch() {
9326 let bytes = [
9327 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
9328 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x01, 0x08, 0x00, 0x43, 0x00, 0x00, 0x80,
9329 0x3F, 0x67, 0x0B,
9330 ];
9331 let module = Module::decode(&bytes).unwrap();
9332 let err = module.validate().unwrap_err();
9333 assert_eq!(err.offset, ByteOffset(29));
9334 assert!(matches!(
9335 err.kind,
9336 ValidationErrorKind::TypeMismatch {
9337 op: "i32.unary",
9338 expected: ValType::Num(crate::types::NumType::I32),
9339 found: ValType::Num(crate::types::NumType::F32),
9340 }
9341 ));
9342 }
9343
9344 #[test]
9345 fn validate_conversions_and_reinterpretations() {
9346 let bytes = [
9347 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x14, 0x05, 0x60, 0x00, 0x01,
9348 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x60, 0x00, 0x01, 0x7D, 0x60, 0x00, 0x01, 0x7C, 0x60,
9349 0x00, 0x00, 0x03, 0x06, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x0A, 0x2A, 0x05, 0x05,
9350 0x00, 0x42, 0x2A, 0xA7, 0x0B, 0x0C, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9351 0xF0, 0x3F, 0xBD, 0x0B, 0x05, 0x00, 0x41, 0x7F, 0xBE, 0x0B, 0x08, 0x00, 0x43, 0x00,
9352 0x00, 0x40, 0x40, 0xBB, 0x0B, 0x06, 0x00, 0x42, 0x7F, 0xC4, 0x1A, 0x0B,
9353 ];
9354 let module = Module::decode(&bytes).unwrap();
9355 module.validate().unwrap();
9356 }
9357
9358 #[test]
9359 fn reject_conversion_type_mismatch() {
9360 let bytes = [
9361 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
9362 0x7F, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x07, 0x01, 0x05, 0x00, 0x41, 0x01, 0xA8, 0x0B,
9363 ];
9364 let module = Module::decode(&bytes).unwrap();
9365 let err = module.validate().unwrap_err();
9366 assert_eq!(err.offset, ByteOffset(26));
9367 assert!(matches!(
9368 err.kind,
9369 ValidationErrorKind::TypeMismatch {
9370 op: "i32.trunc_f32",
9371 expected: ValType::Num(crate::types::NumType::F32),
9372 found: ValType::Num(crate::types::NumType::I32),
9373 }
9374 ));
9375 }
9376
9377 #[test]
9378 fn validate_saturating_truncation_variants() {
9379 let bytes = [
9380 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60, 0x00, 0x01,
9381 0x7F, 0x60, 0x00, 0x01, 0x7E, 0x60, 0x00, 0x01, 0x7D, 0x60, 0x00, 0x01, 0x7C, 0x03,
9382 0x05, 0x04, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x31, 0x04, 0x09, 0x00, 0x43, 0x00, 0x00,
9383 0x80, 0x3F, 0xFC, 0x00, 0x0B, 0x0D, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9384 0xF0, 0x3F, 0xFC, 0x07, 0x0B, 0x09, 0x00, 0x43, 0x00, 0x00, 0x80, 0x3F, 0xFC, 0x04,
9385 0x0B, 0x0D, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0xFC, 0x02,
9386 0x0B,
9387 ];
9388 let module = Module::decode(&bytes).unwrap();
9389 module.validate().unwrap();
9390 }
9391
9392 #[test]
9393 fn reject_saturating_truncation_type_mismatch() {
9394 let bytes = [
9395 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01,
9396 0x7E, 0x03, 0x02, 0x01, 0x00, 0x0A, 0x08, 0x01, 0x06, 0x00, 0x42, 0x00, 0xFC, 0x04,
9397 0x0B,
9398 ];
9399 let module = Module::decode(&bytes).unwrap();
9400 let err = module.validate().unwrap_err();
9401 assert_eq!(err.offset, ByteOffset(26));
9402 assert!(matches!(
9403 err.kind,
9404 ValidationErrorKind::TypeMismatch {
9405 op: "i64.trunc_sat_f32",
9406 expected: ValType::Num(crate::types::NumType::F32),
9407 found: ValType::Num(crate::types::NumType::I64),
9408 }
9409 ));
9410 }
9411}