Skip to content

Commit 3fe5ec8

Browse files
committed
Fix memory64 memory.grow with an immediate delta parameter (#1384)
* extend memory.grow to trigger failure * fix translation of memory.grow with i64.const delta
1 parent 7fd3c5a commit 3fe5ec8

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

crates/ir/src/for_each_op.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5155,7 +5155,7 @@ macro_rules! for_each_op {
51555155
MemoryGrowBy {
51565156
@result: Reg,
51575157
/// The number of pages to add to the memory.
5158-
delta: u32,
5158+
delta: Const32<u64>,
51595159
},
51605160

51615161
/// Wasm `memory.copy` instruction.

crates/wasmi/src/engine/executor/instrs/memory.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
ir::{
77
index::{Data, Memory},
88
Const16,
9+
Const32,
910
Instruction,
1011
Reg,
1112
},
@@ -86,7 +87,7 @@ impl Executor<'_> {
8687
&mut self,
8788
store: &mut Store<T>,
8889
result: Reg,
89-
delta: u32,
90+
delta: Const32<u64>,
9091
) -> Result<(), Error> {
9192
let (store, mut resource_limiter) = store.store_inner_and_resource_limiter_ref();
9293
let delta = u64::from(delta);

crates/wasmi/src/engine/translator/tests/op/memory/memory_grow.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,47 @@ fn reg() {
2121
.run();
2222
}
2323

24-
fn test_imm16(delta: u32) {
24+
fn test_imm32(index_ty: IndexType, memory_index: MemIdx, delta: u32) {
2525
assert!(delta != 0);
26+
let index_ty = index_ty.wat();
2627
let wasm = &format!(
2728
r"
2829
(module
29-
(memory $m 10)
30-
(func (result i32)
31-
(i32.const {delta})
32-
(memory.grow $m)
30+
(memory $mem0 {index_ty} 1)
31+
(memory $mem1 {index_ty} 1)
32+
(func (result {index_ty})
33+
{index_ty}.const {delta}
34+
memory.grow {memory_index}
3335
)
3436
)",
3537
);
3638
TranslationTest::new(wasm)
37-
.expect_func_instrs([
39+
.expect_func_instrs(iter_filter_opts![
3840
Instruction::memory_grow_by(Reg::from(0), delta),
39-
Instruction::memory_index(0),
41+
Instruction::memory_index(memory_index.0),
4042
Instruction::return_reg(Reg::from(0)),
4143
])
4244
.run();
4345
}
4446

4547
#[test]
4648
#[cfg_attr(miri, ignore)]
47-
fn imm16() {
48-
test_imm16(1);
49-
test_imm16(42);
50-
test_imm16(u32::from(u16::MAX) - 1);
51-
test_imm16(u32::from(u16::MAX));
52-
test_imm16(u32::from(u16::MAX) + 1);
53-
test_imm16(u32::MAX - 1);
54-
test_imm16(u32::MAX);
49+
fn imm32() {
50+
for delta in [
51+
1,
52+
42,
53+
u32::from(u16::MAX) - 1,
54+
u32::from(u16::MAX),
55+
u32::from(u16::MAX) + 1,
56+
u32::MAX - 1,
57+
u32::MAX,
58+
] {
59+
for mem_idx in [0, 1].map(MemIdx) {
60+
for index_ty in [IndexType::Memory32, IndexType::Memory64] {
61+
test_imm32(index_ty, mem_idx, delta)
62+
}
63+
}
64+
}
5565
}
5666

5767
#[test]

crates/wasmi/src/engine/translator/visit.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -991,17 +991,24 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
991991

992992
fn visit_memory_grow(&mut self, mem: u32) -> Self::Output {
993993
bail_unreachable!(self);
994-
let delta = self.alloc.stack.pop().map_const(u32::from);
995994
let memory = index::Memory::from(mem);
995+
let memory_type = *self.module.get_type_of_memory(MemoryIdx::from(mem));
996+
let delta = self.alloc.stack.pop();
997+
let delta = self.as_index_type_const32(delta, memory_type.index_ty())?;
996998
let result = self.alloc.stack.push_dynamic()?;
997-
if let Provider::Const(0) = delta {
998-
// Case: growing by 0 pages.
999-
//
1000-
// Since `memory.grow` returns the `memory.size` before the
1001-
// operation a `memory.grow` with `delta` of 0 can be translated
1002-
// as `memory.size` instruction instead.
1003-
self.push_fueled_instr(Instruction::memory_size(result, memory), FuelCosts::entity)?;
1004-
return Ok(());
999+
if let Provider::Const(delta) = delta {
1000+
if u64::from(delta) == 0 {
1001+
// Case: growing by 0 pages.
1002+
//
1003+
// Since `memory.grow` returns the `memory.size` before the
1004+
// operation a `memory.grow` with `delta` of 0 can be translated
1005+
// as `memory.size` instruction instead.
1006+
self.push_fueled_instr(
1007+
Instruction::memory_size(result, memory),
1008+
FuelCosts::entity,
1009+
)?;
1010+
return Ok(());
1011+
}
10051012
}
10061013
let instr = match delta {
10071014
Provider::Const(delta) => Instruction::memory_grow_by(result, delta),

0 commit comments

Comments
 (0)