Commit 216fb648 authored by Ben Smith's avatar Ben Smith Committed by Commit Bot

[wasm] Validate memory.init and memory.drop

The memory.init and memory.drop instructions have a data segment index
that can only be validated by knowing the number of data segments. This
information is provided by the new DataCount section.

Bug: v8:7747
Change-Id: Ie04d57584fe028637f6e931ab53d00abc5b998a4
Reviewed-on: https://chromium-review.googlesource.com/c/1355624Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Ben Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58031}
parent a31338aa
...@@ -1077,12 +1077,21 @@ class WasmDecoder : public Decoder { ...@@ -1077,12 +1077,21 @@ class WasmDecoder : public Decoder {
inline bool Validate(MemoryInitImmediate<validate>& imm) { inline bool Validate(MemoryInitImmediate<validate>& imm) {
if (!Validate(imm.memory)) return false; if (!Validate(imm.memory)) return false;
// TODO(binji): validate imm.data_segment_index if (!VALIDATE(module_ != nullptr &&
imm.data_segment_index <
module_->num_declared_data_segments)) {
errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
return false;
}
return true; return true;
} }
inline bool Validate(MemoryDropImmediate<validate>& imm) { inline bool Validate(MemoryDropImmediate<validate>& imm) {
// TODO(binji): validate imm.data_segment_index if (!VALIDATE(module_ != nullptr &&
imm.index < module_->num_declared_data_segments)) {
errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
return false;
}
return true; return true;
} }
......
...@@ -870,9 +870,9 @@ class ModuleDecoderImpl : public Decoder { ...@@ -870,9 +870,9 @@ class ModuleDecoderImpl : public Decoder {
bool CheckDataSegmentsCount(uint32_t data_segments_count) { bool CheckDataSegmentsCount(uint32_t data_segments_count) {
if (has_seen_unordered_section(kDataCountSectionCode) && if (has_seen_unordered_section(kDataCountSectionCode) &&
data_segments_count != num_declared_data_segments_) { data_segments_count != module_->num_declared_data_segments) {
errorf(pc(), "data segments count %u mismatch (%u expected)", errorf(pc(), "data segments count %u mismatch (%u expected)",
data_segments_count, num_declared_data_segments_); data_segments_count, module_->num_declared_data_segments);
return false; return false;
} }
return true; return true;
...@@ -968,7 +968,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -968,7 +968,7 @@ class ModuleDecoderImpl : public Decoder {
} }
void DecodeDataCountSection() { void DecodeDataCountSection() {
num_declared_data_segments_ = module_->num_declared_data_segments =
consume_count("data segments count", kV8MaxWasmDataSegments); consume_count("data segments count", kV8MaxWasmDataSegments);
} }
...@@ -1120,8 +1120,6 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1120,8 +1120,6 @@ class ModuleDecoderImpl : public Decoder {
"not enough bits"); "not enough bits");
VoidResult intermediate_result_; VoidResult intermediate_result_;
ModuleOrigin origin_; ModuleOrigin origin_;
// The number of data segments as specified by the DataCount section.
uint32_t num_declared_data_segments_ = 0;
bool has_seen_unordered_section(SectionCode section_code) { bool has_seen_unordered_section(SectionCode section_code) {
return seen_unordered_sections_ & (1 << section_code); return seen_unordered_sections_ & (1 << section_code);
......
...@@ -170,6 +170,7 @@ struct V8_EXPORT_PRIVATE WasmModule { ...@@ -170,6 +170,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
uint32_t num_imported_functions = 0; uint32_t num_imported_functions = 0;
uint32_t num_declared_functions = 0; // excluding imported uint32_t num_declared_functions = 0; // excluding imported
uint32_t num_exported_functions = 0; uint32_t num_exported_functions = 0;
uint32_t num_declared_data_segments = 0; // From the DataCount section.
WireBytesRef name = {0, 0}; WireBytesRef name = {0, 0};
std::vector<FunctionSig*> signatures; // by signature index std::vector<FunctionSig*> signatures; // by signature index
std::vector<uint32_t> signature_ids; // by signature index std::vector<uint32_t> signature_ids; // by signature index
......
...@@ -268,6 +268,13 @@ class TestModuleBuilder { ...@@ -268,6 +268,13 @@ class TestModuleBuilder {
return static_cast<byte>(mod.table_inits.size() - 1); return static_cast<byte>(mod.table_inits.size() - 1);
} }
// Set the number of data segments as declared by the DataCount section.
void SetDataSegmentCount(uint32_t data_segment_count) {
// The Data section occurs after the Code section, so we don't need to
// update mod.data_segments, as it is always empty.
mod.num_declared_data_segments = data_segment_count;
}
WasmModule* module() { return &mod; } WasmModule* module() { return &mod; }
private: private:
...@@ -2738,17 +2745,19 @@ TEST_F(FunctionBodyDecoderTest, Regression709741) { ...@@ -2738,17 +2745,19 @@ TEST_F(FunctionBodyDecoderTest, Regression709741) {
TEST_F(FunctionBodyDecoderTest, MemoryInit) { TEST_F(FunctionBodyDecoderTest, MemoryInit) {
TestModuleBuilder builder; TestModuleBuilder builder;
builder.InitializeMemory(); builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module(); module = builder.module();
EXPECT_FAILURE(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO)); EXPECT_FAILURE(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
WASM_FEATURE_SCOPE(bulk_memory); WASM_FEATURE_SCOPE(bulk_memory);
EXPECT_VERIFIES(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO)); EXPECT_VERIFIES(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
// TODO(binji): validate segment index. EXPECT_FAILURE(v_v, WASM_TABLE_INIT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
} }
TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) { TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) {
TestModuleBuilder builder; TestModuleBuilder builder;
builder.InitializeMemory(); builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module(); module = builder.module();
WASM_FEATURE_SCOPE(bulk_memory); WASM_FEATURE_SCOPE(bulk_memory);
...@@ -2760,10 +2769,15 @@ TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) { ...@@ -2760,10 +2769,15 @@ TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) {
} }
TEST_F(FunctionBodyDecoderTest, MemoryDrop) { TEST_F(FunctionBodyDecoderTest, MemoryDrop) {
TestModuleBuilder builder;
builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module();
EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(0)); EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(0));
WASM_FEATURE_SCOPE(bulk_memory); WASM_FEATURE_SCOPE(bulk_memory);
EXPECT_VERIFIES(v_v, WASM_MEMORY_DROP(0)); EXPECT_VERIFIES(v_v, WASM_MEMORY_DROP(0));
// TODO(binji): validate segment index. EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(1));
} }
TEST_F(FunctionBodyDecoderTest, MemoryCopy) { TEST_F(FunctionBodyDecoderTest, MemoryCopy) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment