bug: Unexpected exception triggered by the instruction `memory.init`
erxiaozhou opened this issue · comments
Summary
The test case contains a memory.init
instruction and it is supposed to be valid. However, an unexpected exception indicating "memory OOB" is triggered.
The instructions in the test case.
i32.const 32768
i32.const 4
i32.const 1
memory.init 0
Current State
There is an exception indicating "memory OOB".
Furthermore, the second line is confusing because 0x00008000 is smaller than 0x0000ffff.
[2024-01-16 17:39:10.332] [error] execution failed: out of bounds memory access, Code: 0x408
[2024-01-16 17:39:10.332] [error] Accessing offset from: 0x00008000 to: 0x00008000 , Out of boundary: 0x0000ffff
[2024-01-16 17:39:10.332] [error] In instruction: memory.init (0xfc 0x08) , Bytecode offset: 0x00000141
[2024-01-16 17:39:10.332] [error] When executing function name: "to_test"
Expected State
No exception
Reproduction steps
- Build: ' cmake -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF .. '
- Execute: 'wasmedge --reactor <case_name> to_test'
Case:
all_wamr_memory.init_no_exception.zip
- Get error
Screenshots
Any logs you want to share for showing the specific issue
No response
Components
CLI
WasmEdge Version or Commit you used
Operating system information
Ubuntu 20.04
Hardware Architecture
x86_64
Compiler flags and options
CMake flags: -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_AOT_RUNTIME=OFF
Hi @erxiaozhou , the exception is caused by the fact the input data segment is invalid with size 0.
The memory.init
instruction is used to copy from a passive data segment to linear memory. In the wat sample code, the data segment definition is not provided. By adding some log messages in WasmEdge, I have seen that you defined three active data segments, which would be cleared after memory initialization (check lib/executor/instantiate/data.cpp L83). Therefore, when memory.init
instruction calls setBytes
(defined in file include/runtime/instance/memory.h) to copy the byte (size = 1 in your sample) from the 0-th data segmentat offset 4 to the memory at offset 0x8000, it raises the exception in the second check (i.e. "Check the input data validation"), as Slice.size()
is 0.
Expect<void> setBytes(Span<const Byte> Slice, uint32_t Offset, uint32_t Start,
uint32_t Length) noexcept {
// Check the memory boundary.
if (unlikely(!checkAccessBound(Offset, Length))) {
spdlog::error(ErrCode::Value::MemoryOutOfBounds);
spdlog::error(ErrInfo::InfoBoundary(Offset, Length, getBoundIdx()));
return Unexpect(ErrCode::Value::MemoryOutOfBounds);
}
// Check the input data validation.
if (unlikely(static_cast<uint64_t>(Start) + static_cast<uint64_t>(Length) >
Slice.size())) {
spdlog::error(ErrCode::Value::MemoryOutOfBounds);
spdlog::error(ErrInfo::InfoBoundary(Offset, Length, getBoundIdx()));
return Unexpect(ErrCode::Value::MemoryOutOfBounds);
}
// Copy the data.
if (likely(Length > 0)) {
std::copy(Slice.begin() + Start, Slice.begin() + Start + Length,
DataPtr + Offset);
}
return {};
}
I have tested with the following wat and the corresponding wasm, and it can be executed successfully.
(module
(memory 1)
(data "hello") ;; passive data segment
(func $main (export "_start")
i32.const 32768
i32.const 4
i32.const 1
memory.init 0
)
)
I recommend refining the log message for the "input data validation" check due to its ambiguity, perhaps by introducing another ErrInfo function, such as InfoDataBoundary
? @hydai
I think another error for this case is a good idea, would you like to give a PR?
Sure, I'd love to.
Hi @dannypsnl , I have introduced the error code DataOutOfBounds along with the corresponding error message "out of bounds data access" in include/common/enum.inc. Additionally, I modified the second check in setBytes
as follows:
// Check the input data validation.
if (unlikely(static_cast<uint64_t>(Start) + static_cast<uint64_t>(Length) >
Slice.size())) {
spdlog::error(ErrCode::Value::DataOutOfBounds);
spdlog::error(ErrInfo::InfoBoundary(
Start, Length,
std::max(static_cast<uint32_t>(Slice.size()), UINT32_C(1)) -
UINT32_C(1)));
return Unexpect(ErrCode::Value::DataOutOfBounds);
}
The error report appears as intended:
However, when I run the local test using LD_LIBRARY_PATH=$(pwd)/lib/api ctest, some tests failed due to mismatched error messages like the example shown below:
Given that I am new to the WasmEdge codebase, I have briefly reviewed the test code and noticed that the expected labels are provided in a JSON file (specifically, memory_init.json) generated in the build folder. Could you please guide me on where to modify the code such that the labels in the JSON file would be updated?
No, you will not able to simply fix in this way, because usually we still should report out of memory than out of data instance. There will need a check to split error message.
OK, please update me on any further instructions or actions I can take.