1use crate::prelude::*;
17use crate::{limits::*, *};
18use core::fmt;
19use core::marker;
20use core::ops::Range;
21use core::str;
22
23pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
24
25#[derive(Debug, Clone)]
27pub struct BinaryReaderError {
28 pub(crate) inner: Box<BinaryReaderErrorInner>,
32}
33
34#[derive(Debug, Clone)]
35pub(crate) struct BinaryReaderErrorInner {
36 pub(crate) message: String,
37 pub(crate) kind: BinaryReaderErrorKind,
38 pub(crate) offset: usize,
39 pub(crate) needed_hint: Option<usize>,
40}
41
42#[derive(Debug, Clone, Copy)]
43pub(crate) enum BinaryReaderErrorKind {
44 Custom,
45 Invalid,
46}
47
48pub type Result<T, E = BinaryReaderError> = core::result::Result<T, E>;
50
51#[cfg(feature = "std")]
52impl std::error::Error for BinaryReaderError {}
53
54#[cfg(all(not(feature = "std"), core_error))]
55impl core::error::Error for BinaryReaderError {}
56
57impl fmt::Display for BinaryReaderError {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 write!(
60 f,
61 "{} (at offset 0x{:x})",
62 self.inner.message, self.inner.offset
63 )
64 }
65}
66
67impl BinaryReaderError {
68 #[cold]
69 pub(crate) fn _new(kind: BinaryReaderErrorKind, message: String, offset: usize) -> Self {
70 BinaryReaderError {
71 inner: Box::new(BinaryReaderErrorInner {
72 kind,
73 message,
74 offset,
75 needed_hint: None,
76 }),
77 }
78 }
79
80 #[cold]
81 pub(crate) fn new(message: impl Into<String>, offset: usize) -> Self {
82 Self::_new(BinaryReaderErrorKind::Custom, message.into(), offset)
83 }
84
85 #[cold]
86 pub(crate) fn invalid(msg: &'static str, offset: usize) -> Self {
87 Self::_new(BinaryReaderErrorKind::Invalid, msg.into(), offset)
88 }
89
90 #[cold]
91 pub(crate) fn fmt(args: fmt::Arguments<'_>, offset: usize) -> Self {
92 BinaryReaderError::new(args.to_string(), offset)
93 }
94
95 #[cold]
96 pub(crate) fn eof(offset: usize, needed_hint: usize) -> Self {
97 let mut err = BinaryReaderError::new("unexpected end-of-file", offset);
98 err.inner.needed_hint = Some(needed_hint);
99 err
100 }
101
102 pub(crate) fn kind(&mut self) -> BinaryReaderErrorKind {
103 self.inner.kind
104 }
105
106 pub fn message(&self) -> &str {
108 &self.inner.message
109 }
110
111 pub fn offset(&self) -> usize {
113 self.inner.offset
114 }
115
116 #[cfg(all(feature = "validate", feature = "component-model"))]
117 pub(crate) fn add_context(&mut self, context: String) {
118 self.inner.message = format!("{context}\n{}", self.inner.message);
119 }
120
121 pub(crate) fn set_message(&mut self, message: &str) {
122 self.inner.message = message.to_string();
123 }
124}
125
126#[derive(Clone, Debug, Hash)]
128pub struct BinaryReader<'a> {
129 buffer: &'a [u8],
130 position: usize,
131 original_offset: usize,
132
133 #[cfg(feature = "features")]
145 features: WasmFeatures,
146}
147
148impl<'a> BinaryReader<'a> {
149 pub fn new(data: &[u8], original_offset: usize) -> BinaryReader<'_> {
160 BinaryReader {
161 buffer: data,
162 position: 0,
163 original_offset,
164 #[cfg(feature = "features")]
165 features: WasmFeatures::all(),
166 }
167 }
168
169 #[cfg(feature = "features")]
200 pub fn new_features(
201 data: &[u8],
202 original_offset: usize,
203 features: WasmFeatures,
204 ) -> BinaryReader<'_> {
205 BinaryReader {
206 buffer: data,
207 position: 0,
208 original_offset,
209 features,
210 }
211 }
212
213 pub(crate) fn shrink(&self) -> BinaryReader<'a> {
224 BinaryReader {
225 buffer: &self.buffer[self.position..],
226 position: 0,
227 original_offset: self.original_offset + self.position,
228 #[cfg(feature = "features")]
229 features: self.features,
230 }
231 }
232
233 #[inline]
235 pub fn original_position(&self) -> usize {
236 self.original_offset + self.position
237 }
238
239 #[cfg(feature = "features")]
244 pub fn features(&self) -> WasmFeatures {
245 self.features
246 }
247
248 #[cfg(feature = "features")]
252 pub fn set_features(&mut self, features: WasmFeatures) {
253 self.features = features;
254 }
255
256 pub fn range(&self) -> Range<usize> {
258 self.original_offset..self.original_offset + self.buffer.len()
259 }
260
261 pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
262 &self.buffer[self.position..]
263 }
264
265 fn ensure_has_byte(&self) -> Result<()> {
266 if self.position < self.buffer.len() {
267 Ok(())
268 } else {
269 Err(BinaryReaderError::eof(self.original_position(), 1))
270 }
271 }
272
273 pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
274 if self.position + len <= self.buffer.len() {
275 Ok(())
276 } else {
277 let hint = self.position + len - self.buffer.len();
278 Err(BinaryReaderError::eof(self.original_position(), hint))
279 }
280 }
281
282 #[inline]
285 pub fn read<T>(&mut self) -> Result<T>
286 where
287 T: FromReader<'a>,
288 {
289 T::from_reader(self)
290 }
291
292 pub(crate) fn read_u7(&mut self) -> Result<u8> {
293 let b = self.read_u8()?;
294 if (b & 0x80) != 0 {
295 return Err(BinaryReaderError::new(
296 "invalid u7",
297 self.original_position() - 1,
298 ));
299 }
300 Ok(b)
301 }
302
303 pub(crate) fn external_kind_from_byte(byte: u8, offset: usize) -> Result<ExternalKind> {
304 match byte {
305 0x00 => Ok(ExternalKind::Func),
306 0x01 => Ok(ExternalKind::Table),
307 0x02 => Ok(ExternalKind::Memory),
308 0x03 => Ok(ExternalKind::Global),
309 0x04 => Ok(ExternalKind::Tag),
310 x => Err(Self::invalid_leading_byte_error(x, "external kind", offset)),
311 }
312 }
313
314 pub fn read_size(&mut self, limit: usize, desc: &str) -> Result<usize> {
317 let pos = self.original_position();
318 let size = self.read_var_u32()? as usize;
319 if size > limit {
320 bail!(pos, "{desc} size is out of bounds");
321 }
322 Ok(size)
323 }
324
325 pub fn read_iter<'me, T>(
333 &'me mut self,
334 limit: usize,
335 desc: &str,
336 ) -> Result<BinaryReaderIter<'a, 'me, T>>
337 where
338 T: FromReader<'a>,
339 {
340 let size = self.read_size(limit, desc)?;
341 Ok(BinaryReaderIter {
342 remaining: size,
343 reader: self,
344 _marker: marker::PhantomData,
345 })
346 }
347
348 #[inline]
350 pub fn eof(&self) -> bool {
351 self.position >= self.buffer.len()
352 }
353
354 #[inline]
356 pub fn current_position(&self) -> usize {
357 self.position
358 }
359
360 #[inline]
362 pub fn bytes_remaining(&self) -> usize {
363 self.buffer.len() - self.position
364 }
365
366 pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
372 self.ensure_has_bytes(size)?;
373 let start = self.position;
374 self.position += size;
375 Ok(&self.buffer[start..self.position])
376 }
377
378 pub fn read_reader(&mut self) -> Result<BinaryReader<'a>> {
381 let size = self.read_var_u32()? as usize;
382 self.skip(|reader| {
383 reader.read_bytes(size)?;
384 Ok(())
385 })
386 }
387
388 pub fn read_u32(&mut self) -> Result<u32> {
392 self.ensure_has_bytes(4)?;
393 let word = u32::from_le_bytes(
394 self.buffer[self.position..self.position + 4]
395 .try_into()
396 .unwrap(),
397 );
398 self.position += 4;
399 Ok(word)
400 }
401
402 pub fn read_u64(&mut self) -> Result<u64> {
406 self.ensure_has_bytes(8)?;
407 let word = u64::from_le_bytes(
408 self.buffer[self.position..self.position + 8]
409 .try_into()
410 .unwrap(),
411 );
412 self.position += 8;
413 Ok(word)
414 }
415
416 #[inline]
422 pub fn read_u8(&mut self) -> Result<u8> {
423 let b = match self.buffer.get(self.position) {
424 Some(b) => *b,
425 None => return Err(self.eof_err()),
426 };
427 self.position += 1;
428 Ok(b)
429 }
430
431 #[cold]
432 fn eof_err(&self) -> BinaryReaderError {
433 BinaryReaderError::eof(self.original_position(), 1)
434 }
435
436 #[inline]
444 pub fn read_var_u32(&mut self) -> Result<u32> {
445 let byte = self.read_u8()?;
447 if (byte & 0x80) == 0 {
448 Ok(u32::from(byte))
449 } else {
450 self.read_var_u32_big(byte)
451 }
452 }
453
454 fn read_var_u32_big(&mut self, byte: u8) -> Result<u32> {
455 let mut result = (byte & 0x7F) as u32;
456 let mut shift = 7;
457 loop {
458 let byte = self.read_u8()?;
459 result |= ((byte & 0x7F) as u32) << shift;
460 if shift >= 25 && (byte >> (32 - shift)) != 0 {
461 let msg = if byte & 0x80 != 0 {
462 "invalid var_u32: integer representation too long"
463 } else {
464 "invalid var_u32: integer too large"
465 };
466 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
468 }
469 shift += 7;
470 if (byte & 0x80) == 0 {
471 break;
472 }
473 }
474 Ok(result)
475 }
476
477 #[inline]
485 pub fn read_var_u64(&mut self) -> Result<u64> {
486 let byte = u64::from(self.read_u8()?);
488 if (byte & 0x80) == 0 {
489 Ok(byte)
490 } else {
491 self.read_var_u64_big(byte)
492 }
493 }
494
495 fn read_var_u64_big(&mut self, byte: u64) -> Result<u64> {
496 let mut result = byte & 0x7F;
497 let mut shift = 7;
498 loop {
499 let byte = u64::from(self.read_u8()?);
500 result |= (byte & 0x7F) << shift;
501 if shift >= 57 && (byte >> (64 - shift)) != 0 {
502 let msg = if byte & 0x80 != 0 {
503 "invalid var_u64: integer representation too long"
504 } else {
505 "invalid var_u64: integer too large"
506 };
507 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
509 }
510 shift += 7;
511 if (byte & 0x80) == 0 {
512 break;
513 }
514 }
515 Ok(result)
516 }
517
518 pub fn skip(&mut self, f: impl FnOnce(&mut Self) -> Result<()>) -> Result<Self> {
521 let start = self.position;
522 f(self)?;
523 let mut ret = self.clone();
524 ret.buffer = &self.buffer[start..self.position];
525 ret.position = 0;
526 ret.original_offset = self.original_offset + start;
527 Ok(ret)
528 }
529
530 pub fn skip_string(&mut self) -> Result<()> {
537 let len = self.read_var_u32()? as usize;
538 if len > MAX_WASM_STRING_SIZE {
539 return Err(BinaryReaderError::new(
540 "string size out of bounds",
541 self.original_position() - 1,
542 ));
543 }
544 self.ensure_has_bytes(len)?;
545 self.position += len;
546 Ok(())
547 }
548
549 #[inline]
555 pub fn read_var_i32(&mut self) -> Result<i32> {
556 let byte = self.read_u8()?;
558 if (byte & 0x80) == 0 {
559 Ok(((byte as i32) << 25) >> 25)
560 } else {
561 self.read_var_i32_big(byte)
562 }
563 }
564
565 fn read_var_i32_big(&mut self, byte: u8) -> Result<i32> {
566 let mut result = (byte & 0x7F) as i32;
567 let mut shift = 7;
568 loop {
569 let byte = self.read_u8()?;
570 result |= ((byte & 0x7F) as i32) << shift;
571 if shift >= 25 {
572 let continuation_bit = (byte & 0x80) != 0;
573 let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
574 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
575 let msg = if continuation_bit {
576 "invalid var_i32: integer representation too long"
577 } else {
578 "invalid var_i32: integer too large"
579 };
580 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
581 }
582 return Ok(result);
583 }
584 shift += 7;
585 if (byte & 0x80) == 0 {
586 break;
587 }
588 }
589 let ashift = 32 - shift;
590 Ok((result << ashift) >> ashift)
591 }
592
593 pub fn read_var_s33(&mut self) -> Result<i64> {
599 let byte = self.read_u8()?;
601 if (byte & 0x80) == 0 {
602 return Ok(((byte as i8) << 1) as i64 >> 1);
603 }
604
605 let mut result = (byte & 0x7F) as i64;
606 let mut shift = 7;
607 loop {
608 let byte = self.read_u8()?;
609 result |= ((byte & 0x7F) as i64) << shift;
610 if shift >= 25 {
611 let continuation_bit = (byte & 0x80) != 0;
612 let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
613 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
614 return Err(BinaryReaderError::new(
615 "invalid var_s33: integer representation too long",
616 self.original_position() - 1,
617 ));
618 }
619 return Ok(result);
620 }
621 shift += 7;
622 if (byte & 0x80) == 0 {
623 break;
624 }
625 }
626 let ashift = 64 - shift;
627 Ok((result << ashift) >> ashift)
628 }
629
630 pub fn read_var_i64(&mut self) -> Result<i64> {
636 let mut result: i64 = 0;
637 let mut shift = 0;
638 loop {
639 let byte = self.read_u8()?;
640 result |= i64::from(byte & 0x7F) << shift;
641 if shift >= 57 {
642 let continuation_bit = (byte & 0x80) != 0;
643 let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
644 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
645 let msg = if continuation_bit {
646 "invalid var_i64: integer representation too long"
647 } else {
648 "invalid var_i64: integer too large"
649 };
650 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
651 }
652 return Ok(result);
653 }
654 shift += 7;
655 if (byte & 0x80) == 0 {
656 break;
657 }
658 }
659 let ashift = 64 - shift;
660 Ok((result << ashift) >> ashift)
661 }
662
663 pub fn read_f32(&mut self) -> Result<Ieee32> {
668 let value = self.read_u32()?;
669 Ok(Ieee32(value))
670 }
671
672 pub fn read_f64(&mut self) -> Result<Ieee64> {
677 let value = self.read_u64()?;
678 Ok(Ieee64(value))
679 }
680
681 fn internal_read_string(&mut self, len: usize) -> Result<&'a str> {
683 let bytes = self.read_bytes(len)?;
684 str::from_utf8(bytes).map_err(|_| {
685 BinaryReaderError::new("malformed UTF-8 encoding", self.original_position() - 1)
686 })
687 }
688
689 pub fn read_string(&mut self) -> Result<&'a str> {
697 let len = self.read_var_u32()? as usize;
698 if len > MAX_WASM_STRING_SIZE {
699 return Err(BinaryReaderError::new(
700 "string size out of bounds",
701 self.original_position() - 1,
702 ));
703 }
704 return self.internal_read_string(len);
705 }
706
707 pub fn read_unlimited_string(&mut self) -> Result<&'a str> {
713 let len = self.read_var_u32()? as usize;
714 return self.internal_read_string(len);
715 }
716
717 #[cold]
718 pub(crate) fn invalid_leading_byte<T>(&self, byte: u8, desc: &str) -> Result<T> {
719 Err(Self::invalid_leading_byte_error(
720 byte,
721 desc,
722 self.original_position() - 1,
723 ))
724 }
725
726 pub(crate) fn invalid_leading_byte_error(
727 byte: u8,
728 desc: &str,
729 offset: usize,
730 ) -> BinaryReaderError {
731 format_err!(offset, "invalid leading byte (0x{byte:x}) for {desc}")
732 }
733
734 pub(crate) fn peek(&self) -> Result<u8> {
735 self.ensure_has_byte()?;
736 Ok(self.buffer[self.position])
737 }
738
739 pub(crate) fn read_block_type(&mut self) -> Result<BlockType> {
740 let b = self.peek()?;
741
742 if b & 0x80 == 0 && b & 0x40 != 0 {
759 if b == 0x40 {
760 self.position += 1;
761 return Ok(BlockType::Empty);
762 }
763 return Ok(BlockType::Type(self.read()?));
764 }
765
766 let idx = self.read_var_s33()?;
768 match u32::try_from(idx) {
769 Ok(idx) => Ok(BlockType::FuncType(idx)),
770 Err(_) => {
771 return Err(BinaryReaderError::new(
772 "invalid function type",
773 self.original_position(),
774 ));
775 }
776 }
777 }
778
779 pub fn is_end_then_eof(&self) -> bool {
782 self.remaining_buffer() == &[0x0b]
783 }
784
785 pub(crate) fn read_header_version(&mut self) -> Result<u32> {
786 let magic_number = self.read_bytes(4)?;
787 if magic_number != WASM_MAGIC_NUMBER {
788 return Err(BinaryReaderError::new(
789 format!(
790 "magic header not detected: bad magic number - expected={WASM_MAGIC_NUMBER:#x?} actual={magic_number:#x?}"
791 ),
792 self.original_position() - 4,
793 ));
794 }
795 self.read_u32()
796 }
797}
798
799macro_rules! define_feature_accessor {
802 ($feature:ident = $default:expr) => {
803 impl BinaryReader<'_> {
804 #[inline]
805 #[allow(dead_code)]
806 pub(crate) fn $feature(&self) -> bool {
807 #[cfg(feature = "features")]
808 {
809 self.features.$feature()
810 }
811 #[cfg(not(feature = "features"))]
812 {
813 true
814 }
815 }
816 }
817 };
818}
819
820super::features::foreach_wasm_feature!(define_feature_accessor);
821
822pub struct BinaryReaderIter<'a, 'me, T: FromReader<'a>> {
824 remaining: usize,
825 pub(crate) reader: &'me mut BinaryReader<'a>,
826 _marker: marker::PhantomData<T>,
827}
828
829impl<'a, T> Iterator for BinaryReaderIter<'a, '_, T>
830where
831 T: FromReader<'a>,
832{
833 type Item = Result<T>;
834
835 fn next(&mut self) -> Option<Result<T>> {
836 if self.remaining == 0 {
837 None
838 } else {
839 let ret = self.reader.read::<T>();
840 if ret.is_err() {
841 self.remaining = 0;
842 } else {
843 self.remaining -= 1;
844 }
845 Some(ret)
846 }
847 }
848
849 fn size_hint(&self) -> (usize, Option<usize>) {
850 (self.remaining, Some(self.remaining))
851 }
852}
853
854impl<'a, T> Drop for BinaryReaderIter<'a, '_, T>
855where
856 T: FromReader<'a>,
857{
858 fn drop(&mut self) {
859 while self.next().is_some() {
860 }
862 }
863}