mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-08 12:31:35 +00:00
improve name section parsing
This commit is contained in:
parent
ca99b786ed
commit
6b78411a21
@ -53,8 +53,8 @@ pub use self::func::{Func, FuncBody, Local};
|
|||||||
pub use self::segment::{ElementSegment, DataSegment};
|
pub use self::segment::{ElementSegment, DataSegment};
|
||||||
pub use self::index_map::IndexMap;
|
pub use self::index_map::IndexMap;
|
||||||
pub use self::name_section::{
|
pub use self::name_section::{
|
||||||
NameMap, NameSection, ModuleNameSection, FunctionNameSection,
|
NameMap, NameSection, ModuleNameSubsection, FunctionNameSubsection,
|
||||||
LocalNameSection,
|
LocalNameSubsection,
|
||||||
};
|
};
|
||||||
pub use self::reloc_section::{
|
pub use self::reloc_section::{
|
||||||
RelocSection, RelocationEntry,
|
RelocSection, RelocationEntry,
|
||||||
@ -145,6 +145,10 @@ pub enum Error {
|
|||||||
InvalidSegmentFlags(u32),
|
InvalidSegmentFlags(u32),
|
||||||
/// Sum of counts of locals is greater than 2^32.
|
/// Sum of counts of locals is greater than 2^32.
|
||||||
TooManyLocals,
|
TooManyLocals,
|
||||||
|
/// Duplicated name subsections.
|
||||||
|
DuplicatedNameSubsections(u8),
|
||||||
|
/// Unknown name subsection type.
|
||||||
|
UnknownNameSubsectionType(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -174,7 +178,7 @@ impl fmt::Display for Error {
|
|||||||
Error::InconsistentMetadata => write!(f, "Inconsistent metadata"),
|
Error::InconsistentMetadata => write!(f, "Inconsistent metadata"),
|
||||||
Error::InvalidSectionId(ref id) => write!(f, "Invalid section id: {}", id),
|
Error::InvalidSectionId(ref id) => write!(f, "Invalid section id: {}", id),
|
||||||
Error::SectionsOutOfOrder => write!(f, "Sections out of order"),
|
Error::SectionsOutOfOrder => write!(f, "Sections out of order"),
|
||||||
Error::DuplicatedSections(ref id) => write!(f, "Dupliated sections ({})", id),
|
Error::DuplicatedSections(ref id) => write!(f, "Duplicated sections ({})", id),
|
||||||
Error::InvalidMemoryReference(ref mem_ref) => write!(f, "Invalid memory reference ({})", mem_ref),
|
Error::InvalidMemoryReference(ref mem_ref) => write!(f, "Invalid memory reference ({})", mem_ref),
|
||||||
Error::InvalidTableReference(ref table_ref) => write!(f, "Invalid table reference ({})", table_ref),
|
Error::InvalidTableReference(ref table_ref) => write!(f, "Invalid table reference ({})", table_ref),
|
||||||
Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
|
Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
|
||||||
@ -182,6 +186,8 @@ impl fmt::Display for Error {
|
|||||||
Error::InconsistentCode => write!(f, "Number of function body entries and signatures does not match"),
|
Error::InconsistentCode => write!(f, "Number of function body entries and signatures does not match"),
|
||||||
Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
|
Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
|
||||||
Error::TooManyLocals => write!(f, "Too many locals"),
|
Error::TooManyLocals => write!(f, "Too many locals"),
|
||||||
|
Error::DuplicatedNameSubsections(n) => write!(f, "Duplicated name sections: {}", n),
|
||||||
|
Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,6 +226,8 @@ impl ::std::error::Error for Error {
|
|||||||
Error::InconsistentCode => "Number of function body entries and signatures does not match",
|
Error::InconsistentCode => "Number of function body entries and signatures does not match",
|
||||||
Error::InvalidSegmentFlags(_) => "Invalid segment flags",
|
Error::InvalidSegmentFlags(_) => "Invalid segment flags",
|
||||||
Error::TooManyLocals => "Too many locals",
|
Error::TooManyLocals => "Too many locals",
|
||||||
|
Error::DuplicatedNameSubsections(_) => "Duplicated name sections",
|
||||||
|
Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ impl Module {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to parse name section in place/
|
/// Try to parse name section in place.
|
||||||
///
|
///
|
||||||
/// Corresponding custom section with proper header will convert to name sections
|
/// Corresponding custom section with proper header will convert to name sections
|
||||||
/// If some of them will fail to be decoded, Err variant is returned with the list of
|
/// If some of them will fail to be decoded, Err variant is returned with the list of
|
||||||
@ -364,12 +364,17 @@ impl Module {
|
|||||||
Ok(ns) => ns,
|
Ok(ns) => ns,
|
||||||
Err(e) => { parse_errors.push((i, e)); continue; }
|
Err(e) => { parse_errors.push((i, e)); continue; }
|
||||||
};
|
};
|
||||||
|
if rdr.position() != custom.payload().len() {
|
||||||
|
parse_errors.push((i, io::Error::InvalidData.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
Some(name_section)
|
Some(name_section)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else { None }
|
} else { None }
|
||||||
} {
|
} {
|
||||||
|
// TODO: according to the spec a Wasm binary can contain only one name section
|
||||||
*self.sections.get_mut(i).expect("cannot fail because i in range 0..len; qed") = Section::Name(name_section);
|
*self.sections.get_mut(i).expect("cannot fail because i in range 0..len; qed") = Section::Name(name_section);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,47 @@ const NAME_TYPE_LOCAL: u8 = 2;
|
|||||||
|
|
||||||
/// Debug name information.
|
/// Debug name information.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum NameSection {
|
pub struct NameSection {
|
||||||
/// Module name section.
|
/// Module name subsection.
|
||||||
Module(ModuleNameSection),
|
module_name_subsection: Option<ModuleNameSubsection>,
|
||||||
|
|
||||||
/// Function name section.
|
/// Function name subsection.
|
||||||
Function(FunctionNameSection),
|
function_name_subsection: Option<FunctionNameSubsection>,
|
||||||
|
|
||||||
/// Local name section.
|
/// Local name subsection.
|
||||||
Local(LocalNameSection),
|
local_name_subsection: Option<LocalNameSubsection>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Name section is unparsed.
|
impl NameSection {
|
||||||
Unparsed {
|
/// Module name subsection of this section.
|
||||||
/// The numeric identifier for this name section type.
|
pub fn module_name_subsection(&self) -> Option<&ModuleNameSubsection> {
|
||||||
name_type: u8,
|
self.module_name_subsection.as_ref()
|
||||||
/// The contents of this name section, unparsed.
|
}
|
||||||
name_payload: Vec<u8>,
|
|
||||||
},
|
/// Module name subsection of this section (mutable).
|
||||||
|
pub fn module_name_subsection_mut(&mut self) -> &mut Option<ModuleNameSubsection> {
|
||||||
|
&mut self.module_name_subsection
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Functions name subsection of this section.
|
||||||
|
pub fn function_name_subsection(&self) -> Option<&FunctionNameSubsection> {
|
||||||
|
self.function_name_subsection.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Functions name subsection of this section (mutable).
|
||||||
|
pub fn function_name_subsection_mut(&mut self) -> &mut Option<FunctionNameSubsection> {
|
||||||
|
&mut self.function_name_subsection
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Local name subsection of this section.
|
||||||
|
pub fn local_name_subsection(&self) -> Option<&LocalNameSubsection> {
|
||||||
|
self.local_name_subsection.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Local name subsection of this section (mutable).
|
||||||
|
pub fn local_name_subsection_mut(&mut self) -> &mut Option<LocalNameSubsection> {
|
||||||
|
&mut self.local_name_subsection
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NameSection {
|
impl NameSection {
|
||||||
@ -34,23 +58,50 @@ impl NameSection {
|
|||||||
pub fn deserialize<R: io::Read>(
|
pub fn deserialize<R: io::Read>(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
rdr: &mut R,
|
rdr: &mut R,
|
||||||
) -> Result<NameSection, Error> {
|
) -> Result<Self, Error> {
|
||||||
let name_type: u8 = VarUint7::deserialize(rdr)?.into();
|
let mut module_name_subsection: Option<ModuleNameSubsection> = None;
|
||||||
let name_payload_len: u32 = VarUint32::deserialize(rdr)?.into();
|
let mut function_name_subsection: Option<FunctionNameSubsection> = None;
|
||||||
let name_section = match name_type {
|
let mut local_name_subsection: Option<LocalNameSubsection> = None;
|
||||||
NAME_TYPE_MODULE => NameSection::Module(ModuleNameSection::deserialize(rdr)?),
|
|
||||||
NAME_TYPE_FUNCTION => NameSection::Function(FunctionNameSection::deserialize(module, rdr)?),
|
loop {
|
||||||
NAME_TYPE_LOCAL => NameSection::Local(LocalNameSection::deserialize(module, rdr)?),
|
let subsection_type: u8 = match VarUint7::deserialize(rdr) {
|
||||||
_ => {
|
Ok(raw_subsection_type) => raw_subsection_type.into(),
|
||||||
let mut name_payload = vec![0u8; name_payload_len as usize];
|
// there is no data to read -> there is no other subsections
|
||||||
rdr.read(&mut name_payload)?;
|
Err(Error::UnexpectedEof) => break,
|
||||||
NameSection::Unparsed {
|
Err(error) => return Err(error),
|
||||||
name_type,
|
|
||||||
name_payload,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(name_section)
|
|
||||||
|
match subsection_type {
|
||||||
|
NAME_TYPE_MODULE => {
|
||||||
|
if let Some(_) = module_name_subsection {
|
||||||
|
return Err(Error::DuplicatedNameSubsections(NAME_TYPE_FUNCTION));
|
||||||
|
}
|
||||||
|
module_name_subsection = Some(ModuleNameSubsection::deserialize(rdr)?);
|
||||||
|
},
|
||||||
|
|
||||||
|
NAME_TYPE_FUNCTION => {
|
||||||
|
if let Some(_) = function_name_subsection {
|
||||||
|
return Err(Error::DuplicatedNameSubsections(NAME_TYPE_FUNCTION));
|
||||||
|
}
|
||||||
|
function_name_subsection = Some(FunctionNameSubsection::deserialize(module, rdr)?);
|
||||||
|
},
|
||||||
|
|
||||||
|
NAME_TYPE_LOCAL => {
|
||||||
|
if let Some(_) = local_name_subsection {
|
||||||
|
return Err(Error::DuplicatedNameSubsections(NAME_TYPE_LOCAL));
|
||||||
|
}
|
||||||
|
local_name_subsection = Some(LocalNameSubsection::deserialize(module, rdr)?);
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => return Err(Error::UnknownNameSubsectionType(subsection_type))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(NameSection {
|
||||||
|
module_name_subsection,
|
||||||
|
function_name_subsection,
|
||||||
|
local_name_subsection,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,44 +109,44 @@ impl Serialize for NameSection {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
||||||
let (name_type, name_payload) = match self {
|
fn serialize_subsection<W: io::Write>(wtr: &mut W, name_type: u8, name_payload: &Vec<u8>) -> Result<(), Error> {
|
||||||
NameSection::Module(mod_name) => {
|
|
||||||
let mut buffer = vec![];
|
|
||||||
mod_name.serialize(&mut buffer)?;
|
|
||||||
(NAME_TYPE_MODULE, buffer)
|
|
||||||
}
|
|
||||||
NameSection::Function(fn_names) => {
|
|
||||||
let mut buffer = vec![];
|
|
||||||
fn_names.serialize(&mut buffer)?;
|
|
||||||
(NAME_TYPE_FUNCTION, buffer)
|
|
||||||
}
|
|
||||||
NameSection::Local(local_names) => {
|
|
||||||
let mut buffer = vec![];
|
|
||||||
local_names.serialize(&mut buffer)?;
|
|
||||||
(NAME_TYPE_LOCAL, buffer)
|
|
||||||
}
|
|
||||||
NameSection::Unparsed {
|
|
||||||
name_type,
|
|
||||||
name_payload,
|
|
||||||
} => (name_type, name_payload),
|
|
||||||
};
|
|
||||||
VarUint7::from(name_type).serialize(wtr)?;
|
VarUint7::from(name_type).serialize(wtr)?;
|
||||||
VarUint32::from(name_payload.len()).serialize(wtr)?;
|
VarUint32::from(name_payload.len()).serialize(wtr)?;
|
||||||
wtr.write(&name_payload)?;
|
wtr.write(name_payload).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(module_name_subsection) = self.module_name_subsection {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
module_name_subsection.serialize(&mut buffer)?;
|
||||||
|
serialize_subsection(wtr, NAME_TYPE_MODULE, &buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(function_name_subsection) = self.function_name_subsection {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
function_name_subsection.serialize(&mut buffer)?;
|
||||||
|
serialize_subsection(wtr, NAME_TYPE_FUNCTION, &buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(local_name_subsection) = self.local_name_subsection {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
local_name_subsection.serialize(&mut buffer)?;
|
||||||
|
serialize_subsection(wtr, NAME_TYPE_LOCAL, &buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of this module.
|
/// The name of this module.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ModuleNameSection {
|
pub struct ModuleNameSubsection {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleNameSection {
|
impl ModuleNameSubsection {
|
||||||
/// Create a new module name section with the specified name.
|
/// Create a new module name section with the specified name.
|
||||||
pub fn new<S: Into<String>>(name: S) -> ModuleNameSection {
|
pub fn new<S: Into<String>>(name: S) -> ModuleNameSubsection {
|
||||||
ModuleNameSection { name: name.into() }
|
ModuleNameSubsection { name: name.into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of this module.
|
/// The name of this module.
|
||||||
@ -109,7 +160,7 @@ impl ModuleNameSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for ModuleNameSection {
|
impl Serialize for ModuleNameSubsection {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
||||||
@ -117,22 +168,22 @@ impl Serialize for ModuleNameSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for ModuleNameSection {
|
impl Deserialize for ModuleNameSubsection {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn deserialize<R: io::Read>(rdr: &mut R) -> Result<ModuleNameSection, Error> {
|
fn deserialize<R: io::Read>(rdr: &mut R) -> Result<ModuleNameSubsection, Error> {
|
||||||
let name = String::deserialize(rdr)?;
|
let name = String::deserialize(rdr)?;
|
||||||
Ok(ModuleNameSection { name })
|
Ok(ModuleNameSubsection { name })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The names of the functions in this module.
|
/// The names of the functions in this module.
|
||||||
#[derive(Clone, Debug, Default, PartialEq)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub struct FunctionNameSection {
|
pub struct FunctionNameSubsection {
|
||||||
names: NameMap,
|
names: NameMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionNameSection {
|
impl FunctionNameSubsection {
|
||||||
/// A map from function indices to names.
|
/// A map from function indices to names.
|
||||||
pub fn names(&self) -> &NameMap {
|
pub fn names(&self) -> &NameMap {
|
||||||
&self.names
|
&self.names
|
||||||
@ -147,13 +198,13 @@ impl FunctionNameSection {
|
|||||||
pub fn deserialize<R: io::Read>(
|
pub fn deserialize<R: io::Read>(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
rdr: &mut R,
|
rdr: &mut R,
|
||||||
) -> Result<FunctionNameSection, Error> {
|
) -> Result<FunctionNameSubsection, Error> {
|
||||||
let names = IndexMap::deserialize(module.functions_space(), rdr)?;
|
let names = IndexMap::deserialize(module.functions_space(), rdr)?;
|
||||||
Ok(FunctionNameSection { names })
|
Ok(FunctionNameSubsection { names })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for FunctionNameSection {
|
impl Serialize for FunctionNameSubsection {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
||||||
@ -163,11 +214,11 @@ impl Serialize for FunctionNameSection {
|
|||||||
|
|
||||||
/// The names of the local variables in this module's functions.
|
/// The names of the local variables in this module's functions.
|
||||||
#[derive(Clone, Debug, Default, PartialEq)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub struct LocalNameSection {
|
pub struct LocalNameSubsection {
|
||||||
local_names: IndexMap<NameMap>,
|
local_names: IndexMap<NameMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalNameSection {
|
impl LocalNameSubsection {
|
||||||
/// A map from function indices to a map from variables indices to names.
|
/// A map from function indices to a map from variables indices to names.
|
||||||
pub fn local_names(&self) -> &IndexMap<NameMap> {
|
pub fn local_names(&self) -> &IndexMap<NameMap> {
|
||||||
&self.local_names
|
&self.local_names
|
||||||
@ -184,7 +235,7 @@ impl LocalNameSection {
|
|||||||
pub fn deserialize<R: io::Read>(
|
pub fn deserialize<R: io::Read>(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
rdr: &mut R,
|
rdr: &mut R,
|
||||||
) -> Result<LocalNameSection, Error> {
|
) -> Result<LocalNameSubsection, Error> {
|
||||||
let funcs = module.function_section().ok_or_else(|| {
|
let funcs = module.function_section().ok_or_else(|| {
|
||||||
Error::Other("cannot deserialize local names without a function section")
|
Error::Other("cannot deserialize local names without a function section")
|
||||||
})?;
|
})?;
|
||||||
@ -214,10 +265,10 @@ impl LocalNameSection {
|
|||||||
&deserialize_locals,
|
&deserialize_locals,
|
||||||
rdr,
|
rdr,
|
||||||
)?;
|
)?;
|
||||||
Ok(LocalNameSection { local_names })
|
Ok(LocalNameSubsection { local_names })
|
||||||
}}
|
}}
|
||||||
|
|
||||||
impl Serialize for LocalNameSection {
|
impl Serialize for LocalNameSubsection {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> {
|
||||||
@ -244,20 +295,20 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_module_name() {
|
fn serialize_module_name() {
|
||||||
let original = NameSection::Module(ModuleNameSection::new("my_mod"));
|
let original = NameSection::Module(ModuleNameSubsection::new("my_mod"));
|
||||||
serialize_test(original.clone());
|
serialize_test(original.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_function_names() {
|
fn serialize_function_names() {
|
||||||
let mut sect = FunctionNameSection::default();
|
let mut sect = FunctionNameSubsection::default();
|
||||||
sect.names_mut().insert(0, "hello_world".to_string());
|
sect.names_mut().insert(0, "hello_world".to_string());
|
||||||
serialize_test(NameSection::Function(sect));
|
serialize_test(NameSection::Function(sect));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_local_names() {
|
fn serialize_local_names() {
|
||||||
let mut sect = LocalNameSection::default();
|
let mut sect = LocalNameSubsection::default();
|
||||||
let mut locals = NameMap::default();
|
let mut locals = NameMap::default();
|
||||||
locals.insert(0, "msg".to_string());
|
locals.insert(0, "msg".to_string());
|
||||||
sect.local_names_mut().insert(0, locals);
|
sect.local_names_mut().insert(0, locals);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user