1use core::iter;
2
3use alloc::vec;
4use alloc::vec::Vec;
5
6use crate::{
7 core::{
8 reader::types::{FuncType, ResultType},
9 utils::ToUsizeExt,
10 },
11 NumType, RefType, ValType, ValidationError,
12};
13
14#[derive(Debug, PartialEq, Eq)]
15pub struct ValidationStack {
16 stack: Vec<ValidationStackEntry>,
17 pub ctrl_stack: Vec<CtrlStackEntry>,
19}
20
21impl ValidationStack {
22 pub fn new() -> Self {
24 Self {
25 stack: Vec::new(),
26 ctrl_stack: vec![CtrlStackEntry {
27 label_info: LabelInfo::Untyped,
28 block_ty: FuncType {
29 params: ResultType {
30 valtypes: Vec::new(),
31 },
32 returns: ResultType {
33 valtypes: Vec::new(),
34 },
35 },
36 height: 0,
37 unreachable: false,
38 }],
39 }
40 }
41
42 pub(super) fn new_for_func(block_ty: FuncType) -> Self {
44 Self {
45 stack: Vec::new(),
46 ctrl_stack: vec![CtrlStackEntry {
47 label_info: LabelInfo::Func {
48 stps_to_backpatch: Vec::new(),
49 },
50 block_ty,
51 height: 0,
52 unreachable: false,
53 }],
54 }
55 }
56
57 pub fn len(&self) -> usize {
58 self.stack.len()
59 }
60
61 pub fn push_valtype(&mut self, valtype: ValType) {
62 self.stack.push(ValidationStackEntry::Val(valtype));
63 }
64
65 pub(super) fn drop_val(&mut self) -> Result<(), ValidationError> {
68 self.pop_valtype()
69 .map_err(|_| ValidationError::ExpectedAnOperand)?;
70 Ok(())
71 }
72
73 pub(super) fn make_unspecified(&mut self) -> Result<(), ValidationError> {
80 let last_ctrl_stack_entry = self
81 .ctrl_stack
82 .last_mut()
83 .ok_or(ValidationError::ValidationCtrlStackEmpty)?;
84 last_ctrl_stack_entry.unreachable = true;
85 self.stack.truncate(last_ctrl_stack_entry.height);
86 Ok(())
87 }
88
89 fn pop_valtype(&mut self) -> Result<ValidationStackEntry, ValidationError> {
98 let last_ctrl_stack_entry = self.ctrl_stack.last().unwrap();
102 assert!(self.stack.len() >= last_ctrl_stack_entry.height);
103 if last_ctrl_stack_entry.height == self.stack.len() {
104 if last_ctrl_stack_entry.unreachable {
105 Ok(ValidationStackEntry::Bottom)
106 } else {
107 Err(ValidationError::EndInvalidValueStack)
108 }
109 } else {
110 self.stack
112 .pop()
113 .ok_or(ValidationError::EndInvalidValueStack)
114 }
115 }
116
117 pub fn assert_pop_ref_type(
123 &mut self,
124 expected_ty: Option<RefType>,
125 ) -> Result<(), ValidationError> {
126 match self.pop_valtype()? {
127 ValidationStackEntry::Val(ValType::RefType(ref_type)) => {
128 expected_ty.map_or(Ok(()), |ty| {
129 (ty == ref_type).then_some(()).ok_or(
130 ValidationError::MismatchedRefTypesOnValidationStack {
131 expected: ty,
132 actual: ref_type,
133 },
134 )
135 })
136 }
137 ValidationStackEntry::Val(v) => Err(ValidationError::ExpectedReferenceTypeOnStack(v)),
138 ValidationStackEntry::Bottom => Ok(()),
139 }
140 }
141
142 pub fn assert_pop_val_type(&mut self, expected_ty: ValType) -> Result<(), ValidationError> {
148 match self.pop_valtype()? {
149 ValidationStackEntry::Val(ty) => (ty == expected_ty)
150 .then_some(())
151 .ok_or(ValidationError::InvalidValidationStackValType(Some(ty))),
152 ValidationStackEntry::Bottom => Ok(()),
153 }
154 }
155
156 fn assert_val_types_on_top_with_custom_stacks(
159 stack: &mut Vec<ValidationStackEntry>,
160 ctrl_stack: &[CtrlStackEntry],
161 expected_val_types: &[ValType],
162 unify_to_expected_types: bool,
163 ) -> Result<(), ValidationError> {
164 let last_ctrl_stack_entry = ctrl_stack
165 .last()
166 .ok_or(ValidationError::ValidationCtrlStackEmpty)?;
167 let stack_len = stack.len();
168
169 let rev_iterator = expected_val_types.iter().rev().enumerate();
170 for (i, expected_ty) in rev_iterator {
171 if stack_len - last_ctrl_stack_entry.height <= i {
172 if last_ctrl_stack_entry.unreachable {
173 if unify_to_expected_types {
174 stack.splice(
176 stack_len - i..stack_len - i,
177 expected_val_types[..expected_val_types.len() - i]
178 .iter()
179 .map(|ty| ValidationStackEntry::Val(*ty)),
180 );
181 } else {
182 stack.splice(
183 stack_len - i..stack_len - i,
184 iter::repeat_n(
185 ValidationStackEntry::Bottom,
186 expected_val_types.len() - i,
187 ),
188 );
189 }
190 return Ok(());
191 } else {
192 return Err(ValidationError::EndInvalidValueStack);
193 }
194 }
195
196 let actual_ty = &mut stack[stack_len - i - 1];
198
199 match actual_ty {
200 ValidationStackEntry::Val(actual_val_ty) => {
201 if *actual_val_ty != *expected_ty {
202 return Err(ValidationError::EndInvalidValueStack);
203 }
204 }
205 ValidationStackEntry::Bottom => {
206 if unify_to_expected_types {
208 *actual_ty = ValidationStackEntry::Val(*expected_ty);
209 }
210 }
211 }
212 }
213
214 Ok(())
215 }
216
217 fn assert_val_types_with_custom_stacks(
218 stack: &mut Vec<ValidationStackEntry>,
219 ctrl_stack: &[CtrlStackEntry],
220 expected_val_types: &[ValType],
221 unify_to_expected_types: bool,
222 ) -> Result<(), ValidationError> {
223 ValidationStack::assert_val_types_on_top_with_custom_stacks(
224 stack,
225 ctrl_stack,
226 expected_val_types,
227 unify_to_expected_types,
228 )?;
229 let last_ctrl_stack_entry = &ctrl_stack[ctrl_stack.len() - 1];
231 if stack.len() == last_ctrl_stack_entry.height + expected_val_types.len() {
232 Ok(())
233 } else {
234 Err(ValidationError::EndInvalidValueStack)
235 }
236 }
237
238 pub(super) fn assert_val_types_on_top(
249 &mut self,
250 expected_val_types: &[ValType],
251 unify_to_expected_types: bool,
252 ) -> Result<(), ValidationError> {
253 ValidationStack::assert_val_types_on_top_with_custom_stacks(
254 &mut self.stack,
255 &self.ctrl_stack,
256 expected_val_types,
257 unify_to_expected_types,
258 )
259 }
260
261 pub fn assert_val_types(
271 &mut self,
272 expected_val_types: &[ValType],
273 unify_to_expected_types: bool,
274 ) -> Result<(), ValidationError> {
275 ValidationStack::assert_val_types_with_custom_stacks(
276 &mut self.stack,
277 &self.ctrl_stack,
278 expected_val_types,
279 unify_to_expected_types,
280 )
281 }
282
283 pub fn assert_val_types_of_label_jump_types_on_top(
293 &mut self,
294 label_idx: u32,
295 unify_to_expected_types: bool,
296 ) -> Result<(), ValidationError> {
297 let index_of_label_in_ctrl_stack = self
298 .ctrl_stack
299 .len()
300 .checked_sub(label_idx.into_usize())
301 .and_then(|i| i.checked_sub(1));
302
303 let label_types = index_of_label_in_ctrl_stack
304 .and_then(|index_of_label_in_ctrl_stack| {
305 self.ctrl_stack.get(index_of_label_in_ctrl_stack)
306 })
307 .ok_or(ValidationError::InvalidLabelIdx(label_idx))?
308 .label_types();
309 ValidationStack::assert_val_types_on_top_with_custom_stacks(
310 &mut self.stack,
311 &self.ctrl_stack,
312 label_types,
313 unify_to_expected_types,
314 )
315 }
316
317 pub fn assert_push_ctrl(
326 &mut self,
327 label_info: LabelInfo,
328 block_ty: FuncType,
329 unify_to_expected_types: bool,
330 ) -> Result<(), ValidationError> {
331 self.assert_val_types_on_top(&block_ty.params.valtypes, unify_to_expected_types)?;
332 let height = self.stack.len() - block_ty.params.valtypes.len();
333 self.ctrl_stack.push(CtrlStackEntry {
334 label_info,
335 block_ty,
336 height,
337 unreachable: false,
338 });
339 Ok(())
340 }
341
342 pub fn assert_pop_ctrl(
351 &mut self,
352 unify_to_expected_types: bool,
353 ) -> Result<(LabelInfo, FuncType), ValidationError> {
354 let return_types = &self
355 .ctrl_stack
356 .last()
357 .ok_or(ValidationError::ValidationCtrlStackEmpty)?
358 .block_ty
359 .returns
360 .valtypes;
361 ValidationStack::assert_val_types_with_custom_stacks(
362 &mut self.stack,
363 &self.ctrl_stack,
364 return_types,
365 unify_to_expected_types,
366 )?;
367
368 let last_ctrl_stack_entry = self.ctrl_stack.pop().unwrap();
370 Ok((
371 last_ctrl_stack_entry.label_info,
372 last_ctrl_stack_entry.block_ty,
373 ))
374 }
375
376 pub fn validate_polymorphic_select(&mut self) -> Result<(), ValidationError> {
378 self.assert_pop_val_type(ValType::NumType(crate::NumType::I32))?;
382
383 let first_arg = self.pop_valtype()?;
384 let second_arg = self.pop_valtype()?;
385
386 let unified_type = second_arg
387 .unify(&first_arg)
388 .ok_or(ValidationError::InvalidValidationStackValType(None))?;
389
390 if !(unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::I32)))
392 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::F32)))
393 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::I64)))
394 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::F64)))
395 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::VecType)))
396 {
397 return Err(ValidationError::InvalidValidationStackValType(None));
398 }
399
400 self.stack.push(unified_type);
401 Ok(())
402 }
403}
404
405#[derive(Clone, Debug, PartialEq, Eq)]
407pub enum ValidationStackEntry {
408 Val(ValType),
409 Bottom,
410}
411
412impl ValidationStackEntry {
413 fn unifies_to(&self, other: &ValidationStackEntry) -> bool {
415 match self {
416 ValidationStackEntry::Bottom => true,
417 ValidationStackEntry::Val(_) => self == other,
418 }
419 }
420
421 fn unify(&self, other: &ValidationStackEntry) -> Option<Self> {
423 self.unifies_to(other).then(|| other.clone())
424 }
425}
426
427#[derive(Clone, Debug, PartialEq, Eq)]
429pub struct CtrlStackEntry {
430 pub label_info: LabelInfo,
431 pub block_ty: FuncType,
432 pub height: usize,
433 pub unreachable: bool,
434}
435
436impl CtrlStackEntry {
437 pub fn label_types(&self) -> &[ValType] {
438 if matches!(self.label_info, LabelInfo::Loop { .. }) {
439 &self.block_ty.params.valtypes
440 } else {
441 &self.block_ty.returns.valtypes
442 }
443 }
444}
445
446#[derive(Clone, Debug, PartialEq, Eq)]
450pub enum LabelInfo {
451 Block {
452 stps_to_backpatch: Vec<usize>,
453 },
454 Loop {
455 ip: usize,
456 stp: usize,
457 },
458 If {
459 stps_to_backpatch: Vec<usize>,
460 stp: usize,
461 },
462 Func {
463 stps_to_backpatch: Vec<usize>,
464 },
465 Untyped,
466}
467
468#[cfg(test)]
469mod tests {
470 use crate::{NumType, RefType, ValType};
471
472 use super::{CtrlStackEntry, FuncType, LabelInfo, ResultType, ValidationStack, Vec};
473
474 fn push_dummy_untyped_label(validation_stack: &mut ValidationStack) {
475 validation_stack.ctrl_stack.push(CtrlStackEntry {
476 label_info: LabelInfo::Untyped,
477 block_ty: FuncType {
478 params: ResultType {
479 valtypes: Vec::new(),
480 },
481 returns: ResultType {
482 valtypes: Vec::new(),
483 },
484 },
485 height: validation_stack.len(),
486 unreachable: false,
487 })
488 }
489
490 #[test]
491 fn push_then_pop() {
492 let mut stack = ValidationStack::new();
493
494 stack.push_valtype(ValType::NumType(NumType::F64));
495 stack.push_valtype(ValType::NumType(NumType::I32));
496 stack.push_valtype(ValType::VecType);
497 stack.push_valtype(ValType::RefType(RefType::ExternRef));
498
499 stack
500 .assert_pop_val_type(ValType::RefType(RefType::ExternRef))
501 .unwrap();
502 stack.assert_pop_val_type(ValType::VecType).unwrap();
503 stack
504 .assert_pop_val_type(ValType::NumType(NumType::I32))
505 .unwrap();
506 stack
507 .assert_pop_val_type(ValType::NumType(NumType::F64))
508 .unwrap();
509 }
510
511 #[test]
545 fn assert_valtypes() {
546 let mut stack = ValidationStack::new();
547
548 stack.push_valtype(ValType::NumType(NumType::F64));
549 stack.push_valtype(ValType::NumType(NumType::I32));
550 stack.push_valtype(ValType::NumType(NumType::F32));
551
552 stack
553 .assert_val_types(
554 &[
555 ValType::NumType(NumType::F64),
556 ValType::NumType(NumType::I32),
557 ValType::NumType(NumType::F32),
558 ],
559 true,
560 )
561 .unwrap();
562
563 push_dummy_untyped_label(&mut stack);
564
565 stack.push_valtype(ValType::NumType(NumType::I32));
566
567 stack
568 .assert_val_types(&[ValType::NumType(NumType::I32)], true)
569 .unwrap();
570 }
571
572 #[test]
573 fn assert_emtpy_valtypes() {
574 let mut stack = ValidationStack::new();
575
576 stack.assert_val_types(&[], true).unwrap();
577
578 stack.push_valtype(ValType::NumType(NumType::I32));
579 push_dummy_untyped_label(&mut stack);
580
581 stack.assert_val_types(&[], true).unwrap();
583 }
584
585 #[test]
586 fn assert_valtypes_on_top() {
587 let mut stack = ValidationStack::new();
588
589 stack.assert_val_types_on_top(&[], true).unwrap();
590
591 stack.push_valtype(ValType::NumType(NumType::I32));
592 stack.push_valtype(ValType::NumType(NumType::F32));
593 stack.push_valtype(ValType::NumType(NumType::I64));
594
595 stack.assert_val_types_on_top(&[], true).unwrap();
597
598 stack
599 .assert_val_types_on_top(&[ValType::NumType(NumType::I64)], true)
600 .unwrap();
601
602 stack
603 .assert_val_types_on_top(
604 &[
605 ValType::NumType(NumType::F32),
606 ValType::NumType(NumType::I64),
607 ],
608 true,
609 )
610 .unwrap();
611
612 stack
613 .assert_val_types_on_top(
614 &[
615 ValType::NumType(NumType::I32),
616 ValType::NumType(NumType::F32),
617 ValType::NumType(NumType::I64),
618 ],
619 true,
620 )
621 .unwrap();
622 }
623
624 #[test]
625 fn unspecified() {
626 let mut stack = ValidationStack::new();
627 push_dummy_untyped_label(&mut stack);
628
629 stack.make_unspecified().unwrap();
630
631 stack
633 .assert_pop_val_type(ValType::NumType(NumType::I32))
634 .unwrap();
635
636 stack
637 .assert_pop_val_type(ValType::RefType(RefType::ExternRef))
638 .unwrap();
639
640 stack.ctrl_stack.pop();
644
645 assert_eq!(stack.assert_val_types(&[], true), Ok(()));
647 }
648
649 #[test]
650 fn unspecified2() {
651 let mut stack = ValidationStack::new();
652 push_dummy_untyped_label(&mut stack);
653
654 stack.make_unspecified().unwrap();
655
656 stack
658 .assert_val_types(
659 &[
660 ValType::NumType(NumType::I64),
661 ValType::NumType(NumType::F32),
662 ValType::NumType(NumType::I32),
663 ],
664 true,
665 )
666 .unwrap();
667
668 stack.ctrl_stack.pop();
669
670 assert_eq!(
671 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
672 Ok(())
673 );
674 assert_eq!(
675 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
676 Ok(())
677 );
678 assert_eq!(
679 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
680 Ok(())
681 );
682 }
683
684 #[test]
685 fn unspecified3() {
686 let mut stack = ValidationStack::new();
687 push_dummy_untyped_label(&mut stack);
688
689 stack.make_unspecified().unwrap();
690
691 stack.push_valtype(ValType::NumType(NumType::I32));
692
693 stack
696 .assert_val_types(
697 &[
698 ValType::NumType(NumType::I64),
699 ValType::NumType(NumType::F32),
700 ValType::NumType(NumType::I32),
701 ],
702 true,
703 )
704 .unwrap();
705
706 stack.ctrl_stack.pop();
707
708 assert_eq!(
709 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
710 Ok(())
711 );
712 assert_eq!(
713 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
714 Ok(())
715 );
716 assert_eq!(
717 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
718 Ok(())
719 );
720 }
721
722 #[test]
723 fn unspecified4() {
724 let mut stack = ValidationStack::new();
725
726 stack.push_valtype(ValType::VecType);
727 stack.push_valtype(ValType::NumType(NumType::I32));
728
729 push_dummy_untyped_label(&mut stack);
730
731 stack.make_unspecified().unwrap();
732
733 stack.push_valtype(ValType::VecType);
734 stack.push_valtype(ValType::RefType(RefType::FuncRef));
735
736 stack
739 .assert_val_types(
740 &[
741 ValType::NumType(NumType::I64),
742 ValType::NumType(NumType::F32),
743 ValType::VecType,
744 ValType::RefType(RefType::FuncRef),
745 ],
746 true,
747 )
748 .unwrap();
749
750 stack.ctrl_stack.pop();
751
752 assert_eq!(
753 stack.assert_pop_val_type(ValType::RefType(RefType::FuncRef)),
754 Ok(())
755 );
756 assert_eq!(stack.assert_pop_val_type(ValType::VecType), Ok(()));
757 assert_eq!(
758 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
759 Ok(())
760 );
761 assert_eq!(
762 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
763 Ok(())
764 );
765 assert_eq!(
766 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
767 Ok(())
768 );
769 assert_eq!(stack.assert_pop_val_type(ValType::VecType), Ok(()));
770 }
771}