1use alloc::collections::btree_set::BTreeSet;
2use alloc::vec::Vec;
3use core::iter;
4
5use crate::core::indices::{
6 DataIdx, ElemIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TypeIdx,
7};
8use crate::core::reader::section_header::{SectionHeader, SectionTy};
9use crate::core::reader::span::Span;
10use crate::core::reader::types::element::ElemType;
11use crate::core::reader::types::global::Global;
12use crate::core::reader::types::memarg::MemArg;
13use crate::core::reader::types::{BlockType, FuncType, MemType, NumType, TableType, ValType};
14use crate::core::reader::{WasmReadable, WasmReader};
15use crate::core::sidetable::{Sidetable, SidetableEntry};
16use crate::validation_stack::{LabelInfo, ValidationStack};
17use crate::{RefType, ValidationError};
18
19#[allow(clippy::too_many_arguments)]
20pub fn validate_code_section(
21 wasm: &mut WasmReader,
22 section_header: SectionHeader,
23 fn_types: &[FuncType],
24 type_idx_of_fn: &[usize],
25 num_imported_funcs: usize,
26 globals: &[Global],
27 memories: &[MemType],
28 data_count: &Option<u32>,
29 tables: &[TableType],
30 elements: &[ElemType],
31 validation_context_refs: &BTreeSet<FuncIdx>,
32 sidetable: &mut Sidetable,
33) -> Result<Vec<(Span, usize)>, ValidationError> {
34 assert_eq!(section_header.ty, SectionTy::Code);
35 let code_block_spans_stps = wasm.read_vec_enumerated(|wasm, idx| {
36 let ty_idx = *type_idx_of_fn
40 .get(idx + num_imported_funcs)
41 .ok_or(ValidationError::FunctionAndCodeSectionsHaveDifferentLengths)?;
42 let func_ty = fn_types[ty_idx].clone();
43
44 let func_size = wasm.read_var_u32()?;
45 let func_block = wasm.make_span(func_size as usize)?;
46 let previous_pc = wasm.pc;
47
48 let locals = {
49 let params = func_ty.params.valtypes.iter().cloned();
50 let declared_locals = read_declared_locals(wasm)?;
51 params.chain(declared_locals).collect::<Vec<ValType>>()
52 };
53
54 let mut stack = ValidationStack::new_for_func(func_ty);
55 let stp = sidetable.len();
56
57 read_instructions(
58 wasm,
59 &mut stack,
60 sidetable,
61 &locals,
62 globals,
63 fn_types,
64 type_idx_of_fn,
65 memories,
66 data_count,
67 tables,
68 elements,
69 validation_context_refs,
70 )?;
71
72 if previous_pc + func_size as usize != wasm.pc {
74 return Err(ValidationError::ExprHasTrailingInstructions);
75 }
76
77 Ok((func_block, stp))
78 })?;
79
80 trace!(
81 "Read code section. Found {} code blocks",
82 code_block_spans_stps.len()
83 );
84
85 Ok(code_block_spans_stps)
86}
87
88pub fn read_declared_locals(wasm: &mut WasmReader) -> Result<Vec<ValType>, ValidationError> {
89 let locals = wasm.read_vec(|wasm| {
90 let n = wasm.read_var_u32()? as usize;
91 let valtype = ValType::read(wasm)?;
92
93 Ok((n, valtype))
94 })?;
95
96 let mut total_no_of_locals: usize = 0;
101 for local in &locals {
102 let temp = local.0;
103 if temp > i32::MAX as usize {
104 return Err(ValidationError::TooManyLocals(total_no_of_locals));
105 };
106 total_no_of_locals = match total_no_of_locals.checked_add(temp) {
107 None => return Err(ValidationError::TooManyLocals(total_no_of_locals)),
108 Some(n) => n,
109 }
110 }
111
112 if total_no_of_locals > i32::MAX as usize {
113 return Err(ValidationError::TooManyLocals(total_no_of_locals));
114 }
115
116 let locals = locals
118 .into_iter()
119 .flat_map(|entry| iter::repeat(entry.1).take(entry.0))
120 .collect::<Vec<ValType>>();
121
122 Ok(locals)
123}
124
125fn validate_branch_and_generate_sidetable_entry(
128 wasm: &WasmReader,
129 label_idx: usize,
130 stack: &mut ValidationStack,
131 sidetable: &mut Sidetable,
132 unify_to_expected_types: bool,
133) -> Result<(), ValidationError> {
134 stack.assert_val_types_of_label_jump_types_on_top(label_idx, unify_to_expected_types)?;
135
136 let stack_len = stack.len();
138
139 let index_of_label_in_ctrl_stack = stack
140 .ctrl_stack
141 .len()
142 .checked_sub(label_idx)
143 .and_then(|i| i.checked_sub(1));
144
145 let targeted_ctrl_block_entry = index_of_label_in_ctrl_stack
146 .and_then(|idx| stack.ctrl_stack.get_mut(idx))
147 .ok_or(ValidationError::InvalidLabelIdx(label_idx))?;
148
149 let valcnt = targeted_ctrl_block_entry.label_types().len();
150 let popcnt = stack_len - targeted_ctrl_block_entry.height - valcnt;
151
152 let stp_here = sidetable.len();
163 sidetable.push(SidetableEntry {
164 delta_pc: wasm.pc as isize,
165 delta_stp: stp_here as isize,
166 popcnt,
167 valcnt,
168 });
169
170 match &mut targeted_ctrl_block_entry.label_info {
171 LabelInfo::Block { stps_to_backpatch } => stps_to_backpatch.push(stp_here),
172 LabelInfo::Loop { ip, stp } => {
173 sidetable[stp_here].delta_pc = *ip as isize - wasm.pc as isize;
175 sidetable[stp_here].delta_stp = *stp as isize - stp_here as isize;
176 }
177 LabelInfo::If {
178 stps_to_backpatch, ..
179 } => stps_to_backpatch.push(stp_here),
180 LabelInfo::Func { stps_to_backpatch } => stps_to_backpatch.push(stp_here),
181 LabelInfo::Untyped => {
182 unreachable!("this label is for untyped wasm sequences")
183 }
184 }
185 Ok(())
186}
187
188#[allow(clippy::too_many_arguments)]
189fn read_instructions(
190 wasm: &mut WasmReader,
191 stack: &mut ValidationStack,
192 sidetable: &mut Sidetable,
193 locals: &[ValType],
194 globals: &[Global],
195 fn_types: &[FuncType],
196 type_idx_of_fn: &[usize],
197 memories: &[MemType],
198 data_count: &Option<u32>,
199 tables: &[TableType],
200 elements: &[ElemType],
201 validation_context_refs: &BTreeSet<FuncIdx>,
202) -> Result<(), ValidationError> {
203 loop {
204 let Ok(first_instr_byte) = wasm.read_u8() else {
205 return Err(ValidationError::ExprMissingEnd);
207 };
208
209 #[cfg(debug_assertions)]
210 crate::core::utils::print_beautiful_instruction_name_1_byte(first_instr_byte, wasm.pc);
211
212 #[cfg(not(debug_assertions))]
213 trace!("Read instruction byte {first_instr_byte:#04X?} ({first_instr_byte}) at wasm_binary[{}]", wasm.pc);
214
215 use crate::core::reader::types::opcode::*;
216 match first_instr_byte {
217 NOP => {}
219 BLOCK => {
221 let block_ty = BlockType::read(wasm)?.as_func_type(fn_types)?;
222 let label_info = LabelInfo::Block {
223 stps_to_backpatch: Vec::new(),
224 };
225 stack.assert_push_ctrl(label_info, block_ty, true)?;
229 }
230 LOOP => {
231 let block_ty = BlockType::read(wasm)?.as_func_type(fn_types)?;
232 let label_info = LabelInfo::Loop {
233 ip: wasm.pc,
234 stp: sidetable.len(),
235 };
236 stack.assert_push_ctrl(label_info, block_ty, true)?;
240 }
241 IF => {
242 let block_ty = BlockType::read(wasm)?.as_func_type(fn_types)?;
243
244 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
245
246 let stp_here = sidetable.len();
247 sidetable.push(SidetableEntry {
248 delta_pc: wasm.pc as isize,
249 delta_stp: stp_here as isize,
250 popcnt: 0,
251 valcnt: block_ty.params.valtypes.len(),
252 });
253
254 let label_info = LabelInfo::If {
255 stp: stp_here,
256 stps_to_backpatch: Vec::new(),
257 };
258 stack.assert_push_ctrl(label_info, block_ty, true)?;
262 }
263 ELSE => {
264 let (mut label_info, block_ty) = stack.assert_pop_ctrl(true)?;
265 if let LabelInfo::If {
266 stp,
267 stps_to_backpatch,
268 } = &mut label_info
269 {
270 if *stp == usize::MAX {
271 return Err(ValidationError::ElseWithoutMatchingIf);
273 }
274 let stp_here = sidetable.len();
275 sidetable.push(SidetableEntry {
276 delta_pc: wasm.pc as isize,
277 delta_stp: stp_here as isize,
278 popcnt: 0,
279 valcnt: block_ty.returns.valtypes.len(),
280 });
281 stps_to_backpatch.push(stp_here);
282
283 sidetable[*stp].delta_pc = wasm.pc as isize - sidetable[*stp].delta_pc;
284 sidetable[*stp].delta_stp =
285 sidetable.len() as isize - sidetable[*stp].delta_stp;
286
287 *stp = usize::MAX; for valtype in block_ty.returns.valtypes.iter().rev() {
290 stack.assert_pop_val_type(*valtype)?;
291 }
292
293 for valtype in block_ty.params.valtypes.iter() {
294 stack.push_valtype(*valtype);
295 }
296 stack.assert_push_ctrl(label_info, block_ty, true)?;
300 } else {
301 return Err(ValidationError::ElseWithoutMatchingIf);
302 }
303 }
304 BR => {
305 let label_idx = wasm.read_var_u32()? as LabelIdx;
306 validate_branch_and_generate_sidetable_entry(
307 wasm, label_idx, stack, sidetable, false,
308 )?;
309 stack.make_unspecified()?;
310 }
311 BR_IF => {
312 let label_idx = wasm.read_var_u32()? as LabelIdx;
313 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
314 validate_branch_and_generate_sidetable_entry(
318 wasm, label_idx, stack, sidetable, true,
319 )?;
320 }
321 BR_TABLE => {
322 let label_vec = wasm.read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx))?;
323 let max_label_idx = wasm.read_var_u32()? as LabelIdx;
324 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
325 for label_idx in &label_vec {
326 validate_branch_and_generate_sidetable_entry(
327 wasm, *label_idx, stack, sidetable, false,
328 )?;
329 }
330
331 validate_branch_and_generate_sidetable_entry(
332 wasm,
333 max_label_idx,
334 stack,
335 sidetable,
336 false,
337 )?;
338
339 let max_label_arity = stack
346 .ctrl_stack
347 .get(stack.ctrl_stack.len() - max_label_idx - 1)
348 .unwrap()
349 .label_types()
350 .len();
351 for label_idx in &label_vec {
352 let label_arity = stack
353 .ctrl_stack
354 .get(stack.ctrl_stack.len() - *label_idx - 1)
355 .unwrap()
356 .label_types()
357 .len();
358 if max_label_arity != label_arity {
359 return Err(ValidationError::InvalidLabelIdx(*label_idx));
360 }
361 }
362
363 stack.make_unspecified()?;
364 }
365 END => {
366 let (label_info, block_ty) = stack.assert_pop_ctrl(true)?;
370 let stp_here = sidetable.len();
371
372 match label_info {
373 LabelInfo::Block { stps_to_backpatch } => {
374 stps_to_backpatch.iter().for_each(|i| {
375 sidetable[*i].delta_pc = (wasm.pc as isize) - sidetable[*i].delta_pc;
376 sidetable[*i].delta_stp = (stp_here as isize) - sidetable[*i].delta_stp;
377 });
378 }
379 LabelInfo::If {
380 stp,
381 stps_to_backpatch,
382 } => {
383 if stp != usize::MAX {
384 if !(block_ty.params == block_ty.returns) {
389 return Err(ValidationError::IfWithoutMatchingElse);
390 }
391
392 sidetable[stp].delta_pc = (wasm.pc as isize) - sidetable[stp].delta_pc;
395 sidetable[stp].delta_stp =
396 (stp_here as isize) - sidetable[stp].delta_stp;
397 }
398 stps_to_backpatch.iter().for_each(|i| {
399 sidetable[*i].delta_pc = (wasm.pc as isize) - sidetable[*i].delta_pc;
400 sidetable[*i].delta_stp = (stp_here as isize) - sidetable[*i].delta_stp;
401 });
402 }
403 LabelInfo::Loop { .. } => (),
404 LabelInfo::Func { stps_to_backpatch } => {
405 stps_to_backpatch.iter().for_each(|i| {
408 sidetable[*i].delta_pc =
409 (wasm.pc as isize) - sidetable[*i].delta_pc - 1; sidetable[*i].delta_stp = (stp_here as isize) - sidetable[*i].delta_stp;
411 });
412 }
413 LabelInfo::Untyped => unreachable!("this label is for untyped wasm sequences"),
414 }
415
416 if stack.ctrl_stack.is_empty() {
417 return Ok(());
418 }
419 }
420 RETURN => {
421 let label_idx = stack.ctrl_stack.len() - 1; validate_branch_and_generate_sidetable_entry(
423 wasm, label_idx, stack, sidetable, false,
424 )?;
425 stack.make_unspecified()?;
426 }
427 CALL => {
429 let func_idx = wasm.read_var_u32()? as FuncIdx;
430 let type_idx = *type_idx_of_fn
431 .get(func_idx)
432 .ok_or(ValidationError::FunctionIsNotDefined(func_idx))?;
433 let func_ty = &fn_types[type_idx];
434
435 for typ in func_ty.params.valtypes.iter().rev() {
436 stack.assert_pop_val_type(*typ)?;
437 }
438
439 for typ in func_ty.returns.valtypes.iter() {
440 stack.push_valtype(*typ);
441 }
442 }
443 CALL_INDIRECT => {
444 let type_idx = wasm.read_var_u32()? as TypeIdx;
445
446 let table_idx = wasm.read_var_u32()? as TableIdx;
447
448 let tab = tables
449 .get(table_idx)
450 .ok_or(ValidationError::TableIsNotDefined(table_idx))?;
451
452 if tab.et != RefType::FuncRef {
453 return Err(ValidationError::WrongRefTypeForInteropValue(
454 tab.et,
455 RefType::FuncRef,
456 ));
457 }
458
459 let func_ty = fn_types
460 .get(type_idx)
461 .ok_or(ValidationError::InvalidTypeIdx(type_idx))?;
462
463 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
464
465 for typ in func_ty.params.valtypes.iter().rev() {
466 stack.assert_pop_val_type(*typ)?;
467 }
468
469 for typ in func_ty.returns.valtypes.iter() {
470 stack.push_valtype(*typ);
471 }
472 }
473 UNREACHABLE => {
475 stack.make_unspecified()?;
476 }
477 DROP => {
478 stack.drop_val()?;
479 }
480 SELECT => {
481 stack.validate_polymorphic_select()?;
482 }
483 SELECT_T => {
484 let type_vec = wasm.read_vec(ValType::read)?;
485 if type_vec.len() != 1 {
486 return Err(ValidationError::InvalidSelectTypeVector);
487 }
488 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
489 stack.assert_pop_val_type(type_vec[0])?;
490 stack.assert_pop_val_type(type_vec[0])?;
491 stack.push_valtype(type_vec[0]);
492 }
493 LOCAL_GET => {
495 let local_idx = wasm.read_var_u32()? as LocalIdx;
496 let local_ty = locals
497 .get(local_idx)
498 .ok_or(ValidationError::InvalidLocalIdx)?;
499 stack.push_valtype(*local_ty);
500 }
501 LOCAL_SET => {
503 let local_idx = wasm.read_var_u32()? as LocalIdx;
504 let local_ty = locals
505 .get(local_idx)
506 .ok_or(ValidationError::InvalidLocalIdx)?;
507 stack.assert_pop_val_type(*local_ty)?;
508 }
509 LOCAL_TEE => {
511 let local_idx = wasm.read_var_u32()? as LocalIdx;
512 let local_ty = locals
513 .get(local_idx)
514 .ok_or(ValidationError::InvalidLocalIdx)?;
515 stack.assert_val_types_on_top(&[*local_ty], true)?;
516 }
517 GLOBAL_GET => {
519 let global_idx = wasm.read_var_u32()? as GlobalIdx;
520 let global = globals
521 .get(global_idx)
522 .ok_or(ValidationError::InvalidGlobalIdx(global_idx))?;
523
524 stack.push_valtype(global.ty.ty);
525 trace!(
526 "Instruction: global.get '{}' [] -> [{:?}]",
527 global_idx,
528 global.ty.ty
530 );
531 }
532 GLOBAL_SET => {
534 let global_idx = wasm.read_var_u32()? as GlobalIdx;
535 let global = globals
536 .get(global_idx)
537 .ok_or(ValidationError::InvalidGlobalIdx(global_idx))?;
538
539 if !global.ty.is_mut {
540 return Err(ValidationError::GlobalIsConst);
541 }
542
543 stack.assert_pop_val_type(global.ty.ty)?;
544 }
545 TABLE_GET => {
546 let table_idx = wasm.read_var_u32()? as TableIdx;
547
548 if tables.len() <= table_idx {
549 return Err(ValidationError::TableIsNotDefined(table_idx));
550 }
551
552 let t = tables.get(table_idx).unwrap().et;
553
554 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
555 stack.push_valtype(ValType::RefType(t));
556 }
557 TABLE_SET => {
558 let table_idx = wasm.read_var_u32()? as TableIdx;
559
560 if tables.len() <= table_idx {
561 return Err(ValidationError::TableIsNotDefined(table_idx));
562 }
563
564 let t = tables.get(table_idx).unwrap().et;
565
566 stack.assert_pop_ref_type(Some(t))?;
567 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
568 }
569 I32_LOAD => {
570 if memories.is_empty() {
571 return Err(ValidationError::MemoryIsNotDefined(0));
572 }
573 let memarg = MemArg::read(wasm)?;
574 if memarg.align > 2 {
575 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
576 }
577 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
578 stack.push_valtype(ValType::NumType(NumType::I32));
579 }
580 I64_LOAD => {
581 if memories.is_empty() {
582 return Err(ValidationError::MemoryIsNotDefined(0));
583 }
584 let memarg = MemArg::read(wasm)?;
585 if memarg.align > 3 {
586 return Err(ValidationError::ErroneousAlignment(memarg.align, 3));
587 }
588 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
589 stack.push_valtype(ValType::NumType(NumType::I64));
590 }
591 F32_LOAD => {
592 if memories.is_empty() {
593 return Err(ValidationError::MemoryIsNotDefined(0));
594 }
595 let memarg = MemArg::read(wasm)?;
596 if memarg.align > 2 {
597 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
598 }
599 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
600 stack.push_valtype(ValType::NumType(NumType::F32));
601 }
602 F64_LOAD => {
603 if memories.is_empty() {
604 return Err(ValidationError::MemoryIsNotDefined(0));
605 }
606 let memarg = MemArg::read(wasm)?;
607 if memarg.align > 3 {
608 return Err(ValidationError::ErroneousAlignment(memarg.align, 3));
609 }
610 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
611 stack.push_valtype(ValType::NumType(NumType::F64));
612 }
613 I32_LOAD8_S => {
614 if memories.is_empty() {
615 return Err(ValidationError::MemoryIsNotDefined(0));
616 }
617 let memarg = MemArg::read(wasm)?;
618 if memarg.align > 0 {
619 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
620 }
621 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
622 stack.push_valtype(ValType::NumType(NumType::I32));
623 }
624 I32_LOAD8_U => {
625 if memories.is_empty() {
626 return Err(ValidationError::MemoryIsNotDefined(0));
627 }
628 let memarg = MemArg::read(wasm)?;
629 if memarg.align > 0 {
630 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
631 }
632 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
633 stack.push_valtype(ValType::NumType(NumType::I32));
634 }
635 I32_LOAD16_S => {
636 if memories.is_empty() {
637 return Err(ValidationError::MemoryIsNotDefined(0));
638 }
639 let memarg = MemArg::read(wasm)?;
640 if memarg.align > 1 {
641 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
642 }
643 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
644 stack.push_valtype(ValType::NumType(NumType::I32));
645 }
646 I32_LOAD16_U => {
647 if memories.is_empty() {
648 return Err(ValidationError::MemoryIsNotDefined(0));
649 }
650 let memarg = MemArg::read(wasm)?;
651 if memarg.align > 1 {
652 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
653 }
654 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
655 stack.push_valtype(ValType::NumType(NumType::I32));
656 }
657 I64_LOAD8_S => {
658 if memories.is_empty() {
659 return Err(ValidationError::MemoryIsNotDefined(0));
660 }
661 let memarg = MemArg::read(wasm)?;
662 if memarg.align > 0 {
663 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
664 }
665 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
666 stack.push_valtype(ValType::NumType(NumType::I64));
667 }
668 I64_LOAD8_U => {
669 if memories.is_empty() {
670 return Err(ValidationError::MemoryIsNotDefined(0));
671 }
672 let memarg = MemArg::read(wasm)?;
673 if memarg.align > 0 {
674 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
675 }
676 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
677 stack.push_valtype(ValType::NumType(NumType::I64));
678 }
679 I64_LOAD16_S => {
680 if memories.is_empty() {
681 return Err(ValidationError::MemoryIsNotDefined(0));
682 }
683 let memarg = MemArg::read(wasm)?;
684 if memarg.align > 1 {
685 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
686 }
687 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
688 stack.push_valtype(ValType::NumType(NumType::I64));
689 }
690 I64_LOAD16_U => {
691 if memories.is_empty() {
692 return Err(ValidationError::MemoryIsNotDefined(0));
693 }
694 let memarg = MemArg::read(wasm)?;
695 if memarg.align > 1 {
696 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
697 }
698 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
699 stack.push_valtype(ValType::NumType(NumType::I64));
700 }
701 I64_LOAD32_S => {
702 if memories.is_empty() {
703 return Err(ValidationError::MemoryIsNotDefined(0));
704 }
705 let memarg = MemArg::read(wasm)?;
706 if memarg.align > 2 {
707 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
708 }
709 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
710 stack.push_valtype(ValType::NumType(NumType::I64));
711 }
712 I64_LOAD32_U => {
713 if memories.is_empty() {
714 return Err(ValidationError::MemoryIsNotDefined(0));
715 }
716 let memarg = MemArg::read(wasm)?;
717 if memarg.align > 2 {
718 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
719 }
720 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
721 stack.push_valtype(ValType::NumType(NumType::I64));
722 }
723 I32_STORE => {
724 if memories.is_empty() {
725 return Err(ValidationError::MemoryIsNotDefined(0));
726 }
727 let memarg = MemArg::read(wasm)?;
728 if memarg.align > 2 {
729 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
730 }
731 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
732 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
733 }
734 I64_STORE => {
735 if memories.is_empty() {
736 return Err(ValidationError::MemoryIsNotDefined(0));
737 }
738 let memarg = MemArg::read(wasm)?;
739 if memarg.align > 3 {
740 return Err(ValidationError::ErroneousAlignment(memarg.align, 3));
741 }
742 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
743 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
744 }
745 F32_STORE => {
746 if memories.is_empty() {
747 return Err(ValidationError::MemoryIsNotDefined(0));
748 }
749 let memarg = MemArg::read(wasm)?;
750 if memarg.align > 2 {
751 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
752 }
753 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
754 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
755 }
756 F64_STORE => {
757 if memories.is_empty() {
758 return Err(ValidationError::MemoryIsNotDefined(0));
759 }
760 let memarg = MemArg::read(wasm)?;
761 if memarg.align > 3 {
762 return Err(ValidationError::ErroneousAlignment(memarg.align, 3));
763 }
764 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
765 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
766 }
767 I32_STORE8 => {
768 if memories.is_empty() {
769 return Err(ValidationError::MemoryIsNotDefined(0));
770 }
771 let memarg = MemArg::read(wasm)?;
772 if memarg.align > 0 {
773 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
774 }
775 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
776 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
777 }
778 I32_STORE16 => {
779 if memories.is_empty() {
780 return Err(ValidationError::MemoryIsNotDefined(0));
781 }
782 let memarg = MemArg::read(wasm)?;
783 if memarg.align > 1 {
784 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
785 }
786 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
787 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
788 }
789 I64_STORE8 => {
790 if memories.is_empty() {
791 return Err(ValidationError::MemoryIsNotDefined(0));
792 }
793 let memarg = MemArg::read(wasm)?;
794 if memarg.align > 0 {
795 return Err(ValidationError::ErroneousAlignment(memarg.align, 0));
796 }
797 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
798 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
799 }
800 I64_STORE16 => {
801 if memories.is_empty() {
802 return Err(ValidationError::MemoryIsNotDefined(0));
803 }
804 let memarg = MemArg::read(wasm)?;
805 if memarg.align > 1 {
806 return Err(ValidationError::ErroneousAlignment(memarg.align, 1));
807 }
808 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
809 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
810 }
811 I64_STORE32 => {
812 if memories.is_empty() {
813 return Err(ValidationError::MemoryIsNotDefined(0));
814 }
815 let memarg = MemArg::read(wasm)?;
816 if memarg.align > 2 {
817 return Err(ValidationError::ErroneousAlignment(memarg.align, 2));
818 }
819 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
820 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
821 }
822 MEMORY_SIZE => {
823 let mem_idx = wasm.read_u8()? as MemIdx;
824 if mem_idx != 0 {
825 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
826 }
827 if memories.len() <= mem_idx {
828 return Err(ValidationError::MemoryIsNotDefined(mem_idx));
829 }
830 stack.push_valtype(ValType::NumType(NumType::I32));
831 }
832 MEMORY_GROW => {
833 let mem_idx = wasm.read_u8()? as MemIdx;
834 if mem_idx != 0 {
835 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
836 }
837 if memories.len() <= mem_idx {
838 return Err(ValidationError::MemoryIsNotDefined(mem_idx));
839 }
840 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
841 stack.push_valtype(ValType::NumType(NumType::I32));
842 }
843 I32_CONST => {
845 let _num = wasm.read_var_i32()?;
846 stack.push_valtype(ValType::NumType(NumType::I32));
847 }
848 I64_CONST => {
849 let _num = wasm.read_var_i64()?;
850 stack.push_valtype(ValType::NumType(NumType::I64));
851 }
852 F32_CONST => {
853 let _num = wasm.read_var_f32()?;
854 stack.push_valtype(ValType::NumType(NumType::F32));
855 }
856 F64_CONST => {
857 let _num = wasm.read_var_f64()?;
858 stack.push_valtype(ValType::NumType(NumType::F64));
859 }
860 I32_EQZ => {
861 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
862
863 stack.push_valtype(ValType::NumType(NumType::I32));
864 }
865 I32_EQ | I32_NE | I32_LT_S | I32_LT_U | I32_GT_S | I32_GT_U | I32_LE_S | I32_LE_U
866 | I32_GE_S | I32_GE_U => {
867 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
868 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
869
870 stack.push_valtype(ValType::NumType(NumType::I32));
871 }
872 I64_EQZ => {
873 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
874
875 stack.push_valtype(ValType::NumType(NumType::I32));
876 }
877 I64_EQ | I64_NE | I64_LT_S | I64_LT_U | I64_GT_S | I64_GT_U | I64_LE_S | I64_LE_U
878 | I64_GE_S | I64_GE_U => {
879 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
880 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
881
882 stack.push_valtype(ValType::NumType(NumType::I32));
883 }
884 F32_EQ | F32_NE | F32_LT | F32_GT | F32_LE | F32_GE => {
885 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
886 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
887
888 stack.push_valtype(ValType::NumType(NumType::I32));
889 }
890 F64_EQ | F64_NE | F64_LT | F64_GT | F64_LE | F64_GE => {
891 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
892 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
893
894 stack.push_valtype(ValType::NumType(NumType::I32));
895 }
896 F32_ABS | F32_NEG | F32_CEIL | F32_FLOOR | F32_TRUNC | F32_NEAREST | F32_SQRT => {
897 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
898
899 stack.push_valtype(ValType::NumType(NumType::F32));
900 }
901 F32_ADD | F32_SUB | F32_MUL | F32_DIV | F32_MIN | F32_MAX | F32_COPYSIGN => {
902 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
903 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
904
905 stack.push_valtype(ValType::NumType(NumType::F32));
906 }
907 F64_ABS | F64_NEG | F64_CEIL | F64_FLOOR | F64_TRUNC | F64_NEAREST | F64_SQRT => {
908 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
909
910 stack.push_valtype(ValType::NumType(NumType::F64));
911 }
912 F64_ADD | F64_SUB | F64_MUL | F64_DIV | F64_MIN | F64_MAX | F64_COPYSIGN => {
913 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
914 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
915
916 stack.push_valtype(ValType::NumType(NumType::F64));
917 }
918 I32_ADD | I32_SUB | I32_MUL | I32_DIV_S | I32_DIV_U | I32_REM_S => {
919 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
920 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
921
922 stack.push_valtype(ValType::NumType(NumType::I32));
923 }
924 I32_CLZ | I32_CTZ | I32_POPCNT => {
926 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
927
928 stack.push_valtype(ValType::NumType(NumType::I32));
929 }
930 I32_REM_U | I32_AND | I32_OR | I32_XOR | I32_SHL | I32_SHR_S | I32_SHR_U | I32_ROTL
931 | I32_ROTR => {
932 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
933 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
934
935 stack.push_valtype(ValType::NumType(NumType::I32));
936 }
937 I64_CLZ | I64_CTZ | I64_POPCNT => {
938 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
939
940 stack.push_valtype(ValType::NumType(NumType::I64));
941 }
942
943 I64_ADD | I64_SUB | I64_MUL | I64_DIV_S | I64_DIV_U | I64_REM_S | I64_REM_U
944 | I64_AND | I64_OR | I64_XOR | I64_SHL | I64_SHR_S | I64_SHR_U | I64_ROTL
945 | I64_ROTR => {
946 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
947 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
948
949 stack.push_valtype(ValType::NumType(NumType::I64));
950 }
951
952 I32_WRAP_I64 => {
953 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
954
955 stack.push_valtype(ValType::NumType(NumType::I32));
956 }
957
958 I32_TRUNC_F32_S | I32_TRUNC_F32_U | I32_REINTERPRET_F32 => {
959 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
960
961 stack.push_valtype(ValType::NumType(NumType::I32));
962 }
963
964 I32_TRUNC_F64_S | I32_TRUNC_F64_U => {
965 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
966
967 stack.push_valtype(ValType::NumType(NumType::I32));
968 }
969
970 I64_EXTEND_I32_S | I64_EXTEND_I32_U => {
971 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
972
973 stack.push_valtype(ValType::NumType(NumType::I64));
974 }
975
976 I64_TRUNC_F32_S | I64_TRUNC_F32_U => {
977 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
978
979 stack.push_valtype(ValType::NumType(NumType::I64));
980 }
981
982 I64_TRUNC_F64_S | I64_TRUNC_F64_U | I64_REINTERPRET_F64 => {
983 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
984
985 stack.push_valtype(ValType::NumType(NumType::I64));
986 }
987
988 F32_CONVERT_I32_S | F32_CONVERT_I32_U | F32_REINTERPRET_I32 => {
989 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
990
991 stack.push_valtype(ValType::NumType(NumType::F32));
992 }
993
994 F32_CONVERT_I64_S | F32_CONVERT_I64_U => {
995 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
996
997 stack.push_valtype(ValType::NumType(NumType::F32));
998 }
999
1000 F32_DEMOTE_F64 => {
1001 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1002
1003 stack.push_valtype(ValType::NumType(NumType::F32));
1004 }
1005
1006 F64_CONVERT_I32_S | F64_CONVERT_I32_U => {
1007 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1008
1009 stack.push_valtype(ValType::NumType(NumType::F64));
1010 }
1011
1012 F64_CONVERT_I64_S | F64_CONVERT_I64_U | F64_REINTERPRET_I64 => {
1013 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1014
1015 stack.push_valtype(ValType::NumType(NumType::F64));
1016 }
1017
1018 F64_PROMOTE_F32 => {
1019 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1020
1021 stack.push_valtype(ValType::NumType(NumType::F64));
1022 }
1023
1024 REF_NULL => {
1025 let reftype = RefType::read(wasm)?;
1026 stack.push_valtype(ValType::RefType(reftype));
1028 }
1029
1030 REF_IS_NULL => {
1031 stack.assert_pop_ref_type(None)?;
1032 stack.push_valtype(ValType::NumType(NumType::I32));
1033 }
1034
1035 REF_FUNC => {
1036 let func_idx = wasm.read_var_u32()? as FuncIdx;
1037
1038 if type_idx_of_fn.len() <= func_idx {
1040 return Err(ValidationError::FunctionIsNotDefined(func_idx));
1041 }
1042
1043 if !validation_context_refs.contains(&func_idx) {
1046 return Err(ValidationError::ReferencingAnUnreferencedFunction(func_idx));
1047 }
1048
1049 stack.push_valtype(ValType::RefType(RefType::FuncRef));
1050 }
1051
1052 FC_EXTENSIONS => {
1053 let Ok(second_instr) = wasm.read_var_u32() else {
1054 return Err(ValidationError::ExprMissingEnd);
1056 };
1057
1058 #[cfg(debug_assertions)]
1059 crate::core::utils::print_beautiful_fc_extension(second_instr, wasm.pc);
1060
1061 #[cfg(not(debug_assertions))]
1062 trace!(
1063 "Read instruction byte {second_instr} at wasm_binary[{}]",
1064 wasm.pc
1065 );
1066
1067 use crate::core::reader::types::opcode::fc_extensions::*;
1068 match second_instr {
1069 I32_TRUNC_SAT_F32_S => {
1070 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1071 stack.push_valtype(ValType::NumType(NumType::I32));
1072 }
1073 I32_TRUNC_SAT_F32_U => {
1074 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1075 stack.push_valtype(ValType::NumType(NumType::I32));
1076 }
1077 I32_TRUNC_SAT_F64_S => {
1078 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1079 stack.push_valtype(ValType::NumType(NumType::I32));
1080 }
1081 I32_TRUNC_SAT_F64_U => {
1082 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1083 stack.push_valtype(ValType::NumType(NumType::I32));
1084 }
1085 I64_TRUNC_SAT_F32_S => {
1086 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1087 stack.push_valtype(ValType::NumType(NumType::I64));
1088 }
1089 I64_TRUNC_SAT_F32_U => {
1090 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1091 stack.push_valtype(ValType::NumType(NumType::I64));
1092 }
1093 I64_TRUNC_SAT_F64_S => {
1094 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1095 stack.push_valtype(ValType::NumType(NumType::I64));
1096 }
1097 I64_TRUNC_SAT_F64_U => {
1098 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1099 stack.push_valtype(ValType::NumType(NumType::I64));
1100 }
1101 MEMORY_INIT => {
1102 let data_idx = wasm.read_var_u32()? as DataIdx;
1103 let mem_idx = wasm.read_u8()? as MemIdx;
1104 if mem_idx != 0 {
1105 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1106 }
1107 if memories.len() <= mem_idx {
1108 return Err(ValidationError::MemoryIsNotDefined(mem_idx));
1109 }
1110 if data_count.is_none() {
1111 return Err(ValidationError::NoDataSegments);
1112 }
1113 if data_count.unwrap() as usize <= data_idx {
1114 return Err(ValidationError::DataSegmentNotFound(data_idx));
1115 }
1116 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1117 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1118 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1119 }
1120 DATA_DROP => {
1121 if data_count.is_none() {
1122 return Err(ValidationError::NoDataSegments);
1123 }
1124 let data_idx = wasm.read_var_u32()? as DataIdx;
1125 if data_count.unwrap() as usize <= data_idx {
1126 return Err(ValidationError::DataSegmentNotFound(data_idx));
1127 }
1128 }
1129 MEMORY_COPY => {
1130 let (dst, src) = (wasm.read_u8()? as usize, wasm.read_u8()? as usize);
1131 if dst != 0 || src != 0 {
1132 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1133 }
1134 if memories.is_empty() {
1135 return Err(ValidationError::MemoryIsNotDefined(0));
1136 }
1137 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1138 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1139 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1140 }
1141 MEMORY_FILL => {
1142 let mem_idx = wasm.read_u8()? as MemIdx;
1143 if mem_idx != 0 {
1144 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1145 }
1146 if memories.len() <= mem_idx {
1147 return Err(ValidationError::MemoryIsNotDefined(mem_idx));
1148 }
1149 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1150 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1151 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1152 }
1153 TABLE_INIT => {
1154 let elem_idx = wasm.read_var_u32()? as ElemIdx;
1155 let table_idx = wasm.read_var_u32()? as TableIdx;
1156
1157 if tables.len() <= table_idx {
1158 return Err(ValidationError::TableIsNotDefined(table_idx));
1159 }
1160
1161 let t1 = tables[table_idx].et;
1162
1163 if elements.len() <= elem_idx {
1164 return Err(ValidationError::ElementIsNotDefined(elem_idx));
1165 }
1166
1167 let t2 = elements[elem_idx].to_ref_type();
1168
1169 if t1 != t2 {
1170 return Err(ValidationError::DifferentRefTypes(t1, t2));
1171 }
1172 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1173 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1174 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1176 }
1177 ELEM_DROP => {
1178 let elem_idx = wasm.read_var_u32()? as ElemIdx;
1179
1180 if elements.len() <= elem_idx {
1181 return Err(ValidationError::ElementIsNotDefined(elem_idx));
1182 }
1183 }
1184 TABLE_COPY => {
1185 let table_x_idx = wasm.read_var_u32()? as TableIdx;
1186 let table_y_idx = wasm.read_var_u32()? as TableIdx;
1187
1188 if tables.len() <= table_x_idx {
1189 return Err(ValidationError::TableIsNotDefined(table_x_idx));
1190 }
1191
1192 if tables.len() <= table_y_idx {
1193 return Err(ValidationError::TableIsNotDefined(table_y_idx));
1194 }
1195
1196 let t1 = tables[table_x_idx].et;
1197 let t2 = tables[table_y_idx].et;
1198
1199 if t1 != t2 {
1200 return Err(ValidationError::DifferentRefTypes(t1, t2));
1201 }
1202
1203 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1204 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1205 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1206 }
1207 TABLE_GROW => {
1208 let table_idx = wasm.read_var_u32()? as TableIdx;
1209
1210 if tables.len() <= table_idx {
1211 return Err(ValidationError::TableIsNotDefined(table_idx));
1212 }
1213
1214 let t = tables[table_idx].et;
1215
1216 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1217 stack.assert_pop_ref_type(Some(t))?;
1218
1219 stack.push_valtype(ValType::NumType(NumType::I32));
1220 }
1221 TABLE_SIZE => {
1222 let table_idx = wasm.read_var_u32()? as TableIdx;
1223
1224 if tables.len() <= table_idx {
1225 return Err(ValidationError::TableIsNotDefined(table_idx));
1226 }
1227
1228 stack.push_valtype(ValType::NumType(NumType::I32));
1229 }
1230 TABLE_FILL => {
1231 let table_idx = wasm.read_var_u32()? as TableIdx;
1232
1233 if tables.len() <= table_idx {
1234 return Err(ValidationError::TableIsNotDefined(table_idx));
1235 }
1236
1237 let t = tables[table_idx].et;
1238
1239 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1240 stack.assert_pop_ref_type(Some(t))?;
1241 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1242 }
1243 _ => {
1244 return Err(ValidationError::InvalidMultiByteInstr(
1245 first_instr_byte,
1246 second_instr,
1247 ))
1248 }
1249 }
1250 }
1251
1252 I32_EXTEND8_S => {
1253 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1254
1255 stack.push_valtype(ValType::NumType(NumType::I32));
1256 }
1257 I32_EXTEND16_S => {
1258 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1259
1260 stack.push_valtype(ValType::NumType(NumType::I32));
1261 }
1262 I64_EXTEND8_S => {
1263 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1264
1265 stack.push_valtype(ValType::NumType(NumType::I64));
1266 }
1267 I64_EXTEND16_S => {
1268 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1269
1270 stack.push_valtype(ValType::NumType(NumType::I64));
1271 }
1272 I64_EXTEND32_S => {
1273 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1274
1275 stack.push_valtype(ValType::NumType(NumType::I64));
1276 }
1277
1278 0x06..=0x0A
1280 | 0x12..=0x19
1281 | 0x1C..=0x1F
1282 | 0x25..=0x27
1283 | 0xC0..=0xFA
1284 | 0xFB
1285 | 0xFD
1286 | 0xFE
1287 | 0xFF => {
1288 return Err(ValidationError::InvalidInstr(first_instr_byte));
1289 }
1290 }
1291 }
1292}