Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for value section parsing #1541

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions crates/wasmparser/src/binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,47 @@ impl<'a> BinaryReader<'a> {
BinaryReaderError::eof(self.original_position(), 1)
}

/// Advances the `BinaryReader` up to four bytes to parse a variable
/// length integer as a `u16`.
///
/// # Errors
///
/// If `BinaryReader` has less than one or up to two bytes remaining, or
/// the integer is larger than 16 bits.
#[inline]
pub fn read_var_u16(&mut self) -> Result<u16> {
// Optimization for single byte u16.
let byte = self.read_u8()?;
if (byte & 0x80) == 0 {
Ok(u16::from(byte))
} else {
self.read_var_u16_big(byte)
}
}

fn read_var_u16_big(&mut self, byte: u8) -> Result<u16> {
let mut result = (byte & 0x7F) as u16;
let mut shift = 7;
loop {
let byte = self.read_u8()?;
result |= ((byte & 0x7F) as u16) << shift;
if shift >= 9 && (byte >> (16 - shift)) != 0 {
let msg = if byte & 0x80 != 0 {
"invalid var_u16: integer representation too long"
} else {
"invalid var_u16: integer too large"
};
// The continuation bit or unused bits are set.
return Err(BinaryReaderError::new(msg, self.original_position() - 1));
}
shift += 7;
if (byte & 0x80) == 0 {
break;
}
}
Ok(result)
}

/// Advances the `BinaryReader` up to four bytes to parse a variable
/// length integer as a `u32`.
///
Expand Down Expand Up @@ -519,6 +560,50 @@ impl<'a> BinaryReader<'a> {
Ok(())
}

/// Advances the `BinaryReader` up to four bytes to parse a variable
/// length integer as a `i16`.
/// # Errors
/// If `BinaryReader` has less than one or up to two bytes remaining, or
/// the integer is larger than 16 bits.
#[inline]
pub fn read_var_i16(&mut self) -> Result<i16> {
// Optimization for single byte i16.
let byte = self.read_u8()?;
if (byte & 0x80) == 0 {
Ok(((byte as i16) << 9) >> 9)
} else {
self.read_var_i16_big(byte)
}
}

fn read_var_i16_big(&mut self, byte: u8) -> Result<i16> {
let mut result = (byte & 0x7F) as i16;
let mut shift = 7;
loop {
let byte = self.read_u8()?;
result |= ((byte & 0x7F) as i16) << shift;
if shift >= 9 {
let continuation_bit = (byte & 0x80) != 0;
let sign_and_unused_bit = (byte << 1) as i8 >> (16 - shift);
if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
let msg = if continuation_bit {
"invalid var_i16: integer representation too long"
} else {
"invalid var_i16: integer too large"
};
return Err(BinaryReaderError::new(msg, self.original_position() - 1));
}
return Ok(result);
}
shift += 7;
if (byte & 0x80) == 0 {
break;
}
}
let ashift = 16 - shift;
Ok((result << ashift) >> ashift)
}

/// Advances the `BinaryReader` up to four bytes to parse a variable
/// length integer as a `i32`.
/// # Errors
Expand Down
26 changes: 22 additions & 4 deletions crates/wasmparser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use crate::CoreTypeSectionReader;
use crate::{
limits::MAX_WASM_MODULE_SIZE, BinaryReader, BinaryReaderError, ComponentCanonicalSectionReader,
ComponentExportSectionReader, ComponentImportSectionReader, ComponentInstanceSectionReader,
ComponentStartFunction, ComponentTypeSectionReader, CustomSectionReader, DataSectionReader,
ElementSectionReader, ExportSectionReader, FromReader, FunctionBody, FunctionSectionReader,
GlobalSectionReader, ImportSectionReader, InstanceSectionReader, MemorySectionReader, Result,
SectionLimited, TableSectionReader, TagSectionReader, TypeSectionReader,
ComponentStartFunction, ComponentTypeSectionReader, ComponentValueSectionReader,
CustomSectionReader, DataSectionReader, ElementSectionReader, ExportSectionReader, FromReader,
FunctionBody, FunctionSectionReader, GlobalSectionReader, ImportSectionReader,
InstanceSectionReader, MemorySectionReader, Result, SectionLimited, TableSectionReader,
TagSectionReader, TypeSectionReader,
};
use core::fmt;
use core::iter;
Expand Down Expand Up @@ -275,6 +276,9 @@ pub enum Payload<'a> {
/// A component export section was received, and the provided reader can be
/// used to parse the contents of the component export section.
ComponentExportSection(ComponentExportSectionReader<'a>),
/// A component value section was received, and the provided reader can be
/// used to parse the contents of the component export section.
ComponentValueSection(ComponentValueSectionReader<'a>),

/// A module or component custom section was received.
CustomSection(CustomSectionReader<'a>),
Expand Down Expand Up @@ -328,6 +332,7 @@ const COMPONENT_CANONICAL_SECTION: u8 = 8;
const COMPONENT_START_SECTION: u8 = 9;
const COMPONENT_IMPORT_SECTION: u8 = 10;
const COMPONENT_EXPORT_SECTION: u8 = 11;
const COMPONENT_VALUE_SECTION: u8 = 12;

impl Parser {
/// Creates a new parser.
Expand Down Expand Up @@ -491,6 +496,7 @@ impl Parser {
/// ComponentStartSection { .. } => { /* ... */ }
/// ComponentImportSection(_) => { /* ... */ }
/// ComponentExportSection(_) => { /* ... */ }
/// ComponentValueSection(_) => { /* ... */ }
///
/// ModuleSection { parser, .. }
/// | ComponentSection { parser, .. } => {
Expand Down Expand Up @@ -748,6 +754,12 @@ impl Parser {
ComponentExportSectionReader::new,
ComponentExportSection,
),
(Encoding::Component, COMPONENT_VALUE_SECTION) => section(
reader,
len,
ComponentValueSectionReader::new,
ComponentValueSection,
),
(_, id) => {
let offset = reader.original_position();
let contents = reader.read_bytes(len as usize)?;
Expand Down Expand Up @@ -875,6 +887,7 @@ impl Parser {
/// ComponentStartSection { .. } => { /* ... */ }
/// ComponentImportSection(_) => { /* ... */ }
/// ComponentExportSection(_) => { /* ... */ }
/// ComponentValueSection(_) => { /* ... */}
///
/// CustomSection(_) => { /* ... */ }
///
Expand Down Expand Up @@ -1128,6 +1141,7 @@ impl Payload<'_> {
ComponentStartSection { range, .. } => Some((COMPONENT_START_SECTION, range.clone())),
ComponentImportSection(s) => Some((COMPONENT_IMPORT_SECTION, s.range())),
ComponentExportSection(s) => Some((COMPONENT_EXPORT_SECTION, s.range())),
ComponentValueSection(s) => Some((COMPONENT_VALUE_SECTION, s.range())),

CustomSection(c) => Some((CUSTOM_SECTION, c.range())),

Expand Down Expand Up @@ -1224,6 +1238,10 @@ impl fmt::Debug for Payload<'_> {
.debug_tuple("ComponentExportSection")
.field(&"...")
.finish(),
ComponentValueSection(_) => f
.debug_tuple("ComponentValueSection")
.field(&"...")
.finish(),

CustomSection(c) => f.debug_tuple("CustomSection").field(c).finish(),

Expand Down
2 changes: 2 additions & 0 deletions crates/wasmparser/src/readers/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod instances;
mod names;
mod start;
mod types;
mod values;

pub use self::aliases::*;
pub use self::canonicals::*;
Expand All @@ -15,3 +16,4 @@ pub use self::instances::*;
pub use self::names::*;
pub use self::start::*;
pub use self::types::*;
pub use self::values::*;
Loading