Skip to content

Commit 673e74b

Browse files
authored
Fix some heap type encoding/validation issues (#934)
* Fix some heap type encoding/validation issues * Be sure to encode the index variant of `HeapType` as a signed integer rather than an unsigned integer to have it decoded correctly. * Additionally add a missing validation on `call_ref` and `return_call_ref` to validate the input type before forwarding it to other internal match methods. * Update `check_heap_type`
1 parent f6ae969 commit 673e74b

File tree

5 files changed

+61
-15
lines changed

5 files changed

+61
-15
lines changed

crates/wasm-encoder/src/core/types.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ impl Encode for HeapType {
112112
match self {
113113
HeapType::Func => sink.push(0x70),
114114
HeapType::Extern => sink.push(0x6F),
115-
HeapType::TypedFunc(i) => i.encode(sink),
115+
// Note that this is encoded as a signed type rather than unsigned
116+
// as it's decoded as an s33
117+
HeapType::TypedFunc(i) => i64::from(*i).encode(sink),
116118
}
117119
}
118120
}

crates/wasmparser/src/resources.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
*/
1515

1616
use crate::{
17-
BinaryReaderError, FuncType, GlobalType, MemoryType, RefType, TableType, ValType, WasmFeatures,
17+
BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType, TableType, ValType,
18+
WasmFeatures,
1819
};
1920
use std::ops::Range;
2021

@@ -228,6 +229,27 @@ pub trait WasmModuleResources {
228229
offset: usize,
229230
) -> Result<(), BinaryReaderError>;
230231

232+
/// Checks that a `HeapType` is valid, notably its function index if one is
233+
/// used.
234+
fn check_heap_type(
235+
&self,
236+
heap_type: HeapType,
237+
features: &WasmFeatures,
238+
offset: usize,
239+
) -> Result<(), BinaryReaderError> {
240+
// Delegate to the generic value type validation which will have the
241+
// same validity checks.
242+
self.check_value_type(
243+
RefType {
244+
nullable: true,
245+
heap_type,
246+
}
247+
.into(),
248+
features,
249+
offset,
250+
)
251+
}
252+
231253
/// Returns the number of elements.
232254
fn element_count(&self) -> u32;
233255
/// Returns the number of bytes in the Wasm data section.

crates/wasmparser/src/validator/operators.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,8 @@ where
12961296
Ok(())
12971297
}
12981298
fn visit_call_ref(&mut self, hty: HeapType) -> Self::Output {
1299+
self.resources
1300+
.check_heap_type(hty, &self.features, self.offset)?;
12991301
// If `None` is popped then that means a "bottom" type was popped which
13001302
// is always considered equivalent to the `hty` tag.
13011303
if let Some(rt) = self.pop_ref()? {
@@ -2232,15 +2234,8 @@ where
22322234
Ok(())
22332235
}
22342236
fn visit_ref_null(&mut self, heap_type: HeapType) -> Self::Output {
2235-
self.resources.check_value_type(
2236-
RefType {
2237-
nullable: true,
2238-
heap_type,
2239-
}
2240-
.into(),
2241-
&self.features,
2242-
self.offset,
2243-
)?;
2237+
self.resources
2238+
.check_heap_type(heap_type, &self.features, self.offset)?;
22442239
self.push_operand(ValType::Ref(RefType {
22452240
nullable: true,
22462241
heap_type,

crates/wast/src/core/binary.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,11 @@ impl<'a> Encode for HeapType<'a> {
241241
HeapType::Struct => e.push(0x67),
242242
HeapType::Array => e.push(0x66),
243243
HeapType::I31 => e.push(0x6a),
244-
HeapType::Index(index) => {
245-
index.encode(e);
244+
// Note that this is encoded as a signed leb128 so be sure to cast
245+
// to an i64 first
246+
HeapType::Index(Index::Num(n, _)) => i64::from(*n).encode(e),
247+
HeapType::Index(Index::Id(n)) => {
248+
panic!("unresolved index in emission: {:?}", n)
246249
}
247250
}
248251
}
@@ -427,8 +430,14 @@ impl Encode for Table<'_> {
427430
fn encode(&self, e: &mut Vec<u8>) {
428431
assert!(self.exports.names.is_empty());
429432
match &self.kind {
430-
TableKind::Normal { ty, init_expr: None } => ty.encode(e),
431-
TableKind::Normal { ty, init_expr: Some(init_expr) } => {
433+
TableKind::Normal {
434+
ty,
435+
init_expr: None,
436+
} => ty.encode(e),
437+
TableKind::Normal {
438+
ty,
439+
init_expr: Some(init_expr),
440+
} => {
432441
e.push(0x40);
433442
e.push(0x00);
434443
ty.encode(e);

tests/local/function-references/bad-call-ref-ty.wast

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,21 @@
1515
)
1616
)
1717
"expected i32 but nothing on stack")
18+
19+
(assert_invalid
20+
(module
21+
(type $t (func ))
22+
(func (param $f (ref $t))
23+
(call_ref 5 (local.get $f))
24+
)
25+
)
26+
"type index out of bounds")
27+
28+
(assert_invalid
29+
(module
30+
(type $t (func ))
31+
(func (param $f (ref $t))
32+
(call_ref 100 (local.get $f))
33+
)
34+
)
35+
"type index out of bounds")

0 commit comments

Comments
 (0)