1 //! Elements of the WebAssembly binary format.
2
3 use alloc::{string::String, vec::Vec};
4 use crate::io;
5
6 use core::fmt;
7
8 macro_rules! buffered_read {
9 ($buffer_size: expr, $length: expr, $reader: expr) => {
10 {
11 let mut vec_buf = Vec::new();
12 let mut total_read = 0;
13 let mut buf = [0u8; $buffer_size];
14 while total_read < $length {
15 let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
16 $reader.read(&mut buf[0..next_to_read])?;
17 vec_buf.extend_from_slice(&buf[0..next_to_read]);
18 total_read += next_to_read;
19 }
20 vec_buf
21 }
22 }
23 }
24
25 mod primitives;
26 mod module;
27 mod section;
28 mod types;
29 mod import_entry;
30 mod export_entry;
31 mod global_entry;
32 mod ops;
33 mod func;
34 mod segment;
35 mod index_map;
36 mod name_section;
37 mod reloc_section;
38
39 pub use self::module::{Module, peek_size, ImportCountType};
40 pub use self::section::{
41 Section, FunctionSection, CodeSection, MemorySection, DataSection,
42 ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
43 TableSection, CustomSection,
44 };
45 pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
46 pub use self::export_entry::{ExportEntry, Internal};
47 pub use self::global_entry::GlobalEntry;
48 pub use self::primitives::{
49 VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
50 Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
51 };
52 pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
53 pub use self::ops::{Instruction, Instructions, InitExpr, opcodes, BrTableData};
54
55 #[cfg(feature="atomics")]
56 pub use self::ops::AtomicsInstruction;
57
58 #[cfg(feature="simd")]
59 pub use self::ops::SimdInstruction;
60
61 #[cfg(feature="sign_ext")]
62 pub use self::ops::SignExtInstruction;
63
64 #[cfg(feature="bulk")]
65 pub use self::ops::BulkInstruction;
66
67 #[cfg(any(feature="simd", feature="atomics"))]
68 pub use self::ops::MemArg;
69
70 pub use self::func::{Func, FuncBody, Local};
71 pub use self::segment::{ElementSegment, DataSegment};
72 pub use self::index_map::IndexMap;
73 pub use self::name_section::{
74 NameMap, NameSection, ModuleNameSubsection, FunctionNameSubsection,
75 LocalNameSubsection,
76 };
77 pub use self::reloc_section::{
78 RelocSection, RelocationEntry,
79 };
80
81 /// Deserialization from serial i/o.
82 pub trait Deserialize : Sized {
83 /// Serialization error produced by deserialization routine.
84 type Error: From<io::Error>;
85 /// Deserialize type from serial i/o
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>86 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
87 }
88
89 /// Serialization to serial i/o. Takes self by value to consume less memory
90 /// (parity-wasm IR is being partially freed by filling the result buffer).
91 pub trait Serialize {
92 /// Serialization error produced by serialization routine.
93 type Error: From<io::Error>;
94 /// Serialize type to serial i/o
serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>95 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
96 }
97
98 /// Deserialization/serialization error
99 #[derive(Debug, Clone)]
100 pub enum Error {
101 /// Unexpected end of input.
102 UnexpectedEof,
103 /// Invalid magic.
104 InvalidMagic,
105 /// Unsupported version.
106 UnsupportedVersion(u32),
107 /// Inconsistence between declared and actual length.
108 InconsistentLength {
109 /// Expected length of the definition.
110 expected: usize,
111 /// Actual length of the definition.
112 actual: usize
113 },
114 /// Other static error.
115 Other(&'static str),
116 /// Other allocated error.
117 HeapOther(String),
118 /// Invalid/unknown value type declaration.
119 UnknownValueType(i8),
120 /// Invalid/unknown table element type declaration.
121 UnknownTableElementType(i8),
122 /// Non-utf8 string.
123 NonUtf8String,
124 /// Unknown external kind code.
125 UnknownExternalKind(u8),
126 /// Unknown internal kind code.
127 UnknownInternalKind(u8),
128 /// Unknown opcode encountered.
129 UnknownOpcode(u8),
130 #[cfg(feature="simd")]
131 /// Unknown SIMD opcode encountered.
132 UnknownSimdOpcode(u32),
133 /// Invalid VarUint1 value.
134 InvalidVarUint1(u8),
135 /// Invalid VarInt32 value.
136 InvalidVarInt32,
137 /// Invalid VarInt64 value.
138 InvalidVarInt64,
139 /// Invalid VarUint32 value.
140 InvalidVarUint32,
141 /// Invalid VarUint64 value.
142 InvalidVarUint64,
143 /// Inconsistent metadata.
144 InconsistentMetadata,
145 /// Invalid section id.
146 InvalidSectionId(u8),
147 /// Sections are out of order.
148 SectionsOutOfOrder,
149 /// Duplicated sections.
150 DuplicatedSections(u8),
151 /// Invalid memory reference (should be 0).
152 InvalidMemoryReference(u8),
153 /// Invalid table reference (should be 0).
154 InvalidTableReference(u8),
155 /// Invalid value used for flags in limits type.
156 InvalidLimitsFlags(u8),
157 /// Unknown function form (should be 0x60).
158 UnknownFunctionForm(u8),
159 /// Invalid varint7 (should be in -64..63 range).
160 InvalidVarInt7(u8),
161 /// Number of function body entries and signatures does not match.
162 InconsistentCode,
163 /// Only flags 0, 1, and 2 are accepted on segments.
164 InvalidSegmentFlags(u32),
165 /// Sum of counts of locals is greater than 2^32.
166 TooManyLocals,
167 /// Duplicated name subsections.
168 DuplicatedNameSubsections(u8),
169 /// Unknown name subsection type.
170 UnknownNameSubsectionType(u8),
171 }
172
173 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 match *self {
176 Error::UnexpectedEof => write!(f, "Unexpected end of input"),
177 Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
178 Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
179 Error::InconsistentLength { expected, actual } => {
180 write!(f, "Expected length {}, found {}", expected, actual)
181 }
182 Error::Other(msg) => write!(f, "{}", msg),
183 Error::HeapOther(ref msg) => write!(f, "{}", msg),
184 Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
185 Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
186 Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
187 Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
188 Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
189 Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
190 #[cfg(feature="simd")]
191 Error::UnknownSimdOpcode(opcode) => write!(f, "Unknown SIMD opcode {}", opcode),
192 Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
193 Error::InvalidVarInt7(val) => write!(f, "Not a signed 7-bit integer: {}", val),
194 Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
195 Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
196 Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
197 Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
198 Error::InconsistentMetadata => write!(f, "Inconsistent metadata"),
199 Error::InvalidSectionId(ref id) => write!(f, "Invalid section id: {}", id),
200 Error::SectionsOutOfOrder => write!(f, "Sections out of order"),
201 Error::DuplicatedSections(ref id) => write!(f, "Duplicated sections ({})", id),
202 Error::InvalidMemoryReference(ref mem_ref) => write!(f, "Invalid memory reference ({})", mem_ref),
203 Error::InvalidTableReference(ref table_ref) => write!(f, "Invalid table reference ({})", table_ref),
204 Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
205 Error::UnknownFunctionForm(ref form) => write!(f, "Unknown function form ({})", form),
206 Error::InconsistentCode => write!(f, "Number of function body entries and signatures does not match"),
207 Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
208 Error::TooManyLocals => write!(f, "Too many locals"),
209 Error::DuplicatedNameSubsections(n) => write!(f, "Duplicated name subsections: {}", n),
210 Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
211 }
212 }
213 }
214
215 #[cfg(feature = "std")]
216 impl ::std::error::Error for Error {
description(&self) -> &str217 fn description(&self) -> &str {
218 match *self {
219 Error::UnexpectedEof => "Unexpected end of input",
220 Error::InvalidMagic => "Invalid magic number at start of file",
221 Error::UnsupportedVersion(_) => "Unsupported wasm version",
222 Error::InconsistentLength { .. } => "Inconsistent length",
223 Error::Other(msg) => msg,
224 Error::HeapOther(ref msg) => &msg[..],
225 Error::UnknownValueType(_) => "Invalid or unknown value type",
226 Error::UnknownTableElementType(_) => "Unknown table element type",
227 Error::NonUtf8String => "Non-UTF-8 string",
228 Error::UnknownExternalKind(_) => "Unknown external kind",
229 Error::UnknownInternalKind(_) => "Unknown internal kind",
230 Error::UnknownOpcode(_) => "Unknown opcode",
231 #[cfg(feature="simd")]
232 Error::UnknownSimdOpcode(_) => "Unknown SIMD opcode",
233 Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
234 Error::InvalidVarInt32 => "Not a signed 32-bit integer",
235 Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
236 Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
237 Error::InvalidVarInt64 => "Not a signed 64-bit integer",
238 Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
239 Error::InconsistentMetadata => "Inconsistent metadata",
240 Error::InvalidSectionId(_) => "Invalid section id",
241 Error::SectionsOutOfOrder => "Sections out of order",
242 Error::DuplicatedSections(_) => "Duplicated section",
243 Error::InvalidMemoryReference(_) => "Invalid memory reference",
244 Error::InvalidTableReference(_) => "Invalid table reference",
245 Error::InvalidLimitsFlags(_) => "Invalid limits flags",
246 Error::UnknownFunctionForm(_) => "Unknown function form",
247 Error::InconsistentCode => "Number of function body entries and signatures does not match",
248 Error::InvalidSegmentFlags(_) => "Invalid segment flags",
249 Error::TooManyLocals => "Too many locals",
250 Error::DuplicatedNameSubsections(_) => "Duplicated name subsections",
251 Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
252 }
253 }
254 }
255
256 impl From<io::Error> for Error {
from(err: io::Error) -> Self257 fn from(err: io::Error) -> Self {
258 Error::HeapOther(format!("I/O Error: {:?}", err))
259 }
260 }
261
262 // These are emitted by section parsers, such as `parse_names` and `parse_reloc`.
263 impl From<(Vec<(usize, Error)>, Module)> for Error {
from(err: (Vec<(usize, Error)>, Module)) -> Self264 fn from(err: (Vec<(usize, Error)>, Module)) -> Self {
265 let ret = err.0.iter()
266 .fold(
267 String::new(),
268 |mut acc, item| { acc.push_str(&format!("In section {}: {}\n", item.0, item.1)); acc }
269 );
270 Error::HeapOther(ret)
271 }
272 }
273
274 /// Unparsed part of the module/section.
275 pub struct Unparsed(pub Vec<u8>);
276
277 impl Deserialize for Unparsed {
278 type Error = Error;
279
deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>280 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
281 let len = VarUint32::deserialize(reader)?.into();
282 let mut vec = vec![0u8; len];
283 reader.read(&mut vec[..])?;
284 Ok(Unparsed(vec))
285 }
286 }
287
288 impl From<Unparsed> for Vec<u8> {
from(u: Unparsed) -> Vec<u8>289 fn from(u: Unparsed) -> Vec<u8> {
290 u.0
291 }
292 }
293
294 /// Deserialize deserializable type from buffer.
deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error>295 pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
296 let mut reader = io::Cursor::new(contents);
297 let result = T::deserialize(&mut reader)?;
298 if reader.position() != contents.len() {
299 // It's a TrailingData, since if there is not enough data then
300 // UnexpectedEof must have been returned earlier in T::deserialize.
301 return Err(io::Error::TrailingData.into())
302 }
303 Ok(result)
304 }
305
306 /// Create buffer with serialized value.
serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error>307 pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
308 let mut buf = Vec::new();
309 val.serialize(&mut buf)?;
310 Ok(buf)
311 }
312
313 /// Deserialize module from the file.
314 #[cfg(feature = "std")]
deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error>315 pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
316 let mut f = ::std::fs::File::open(p)
317 .map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;
318
319 Module::deserialize(&mut f)
320 }
321
322 /// Serialize module to the file
323 #[cfg(feature = "std")]
serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>324 pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
325 let mut io = ::std::fs::File::create(p)
326 .map_err(|e|
327 Error::HeapOther(format!("Can't create the file: {:?}", e))
328 )?;
329
330 module.serialize(&mut io)?;
331 Ok(())
332 }
333