[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/1355624
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Ben Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58031}
This commit is contained in:
Ben Smith 2018-11-29 15:14:42 -08:00 committed by Commit Bot
parent a31338aa08
commit 216fb64816
4 changed files with 31 additions and 9 deletions

View File

@ -1077,12 +1077,21 @@ class WasmDecoder : public Decoder {
inline bool Validate(MemoryInitImmediate<validate>& imm) {
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;
}
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;
}

View File

@ -870,9 +870,9 @@ class ModuleDecoderImpl : public Decoder {
bool CheckDataSegmentsCount(uint32_t data_segments_count) {
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)",
data_segments_count, num_declared_data_segments_);
data_segments_count, module_->num_declared_data_segments);
return false;
}
return true;
@ -968,7 +968,7 @@ class ModuleDecoderImpl : public Decoder {
}
void DecodeDataCountSection() {
num_declared_data_segments_ =
module_->num_declared_data_segments =
consume_count("data segments count", kV8MaxWasmDataSegments);
}
@ -1120,8 +1120,6 @@ class ModuleDecoderImpl : public Decoder {
"not enough bits");
VoidResult intermediate_result_;
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) {
return seen_unordered_sections_ & (1 << section_code);

View File

@ -170,6 +170,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
uint32_t num_imported_functions = 0;
uint32_t num_declared_functions = 0; // excluding imported
uint32_t num_exported_functions = 0;
uint32_t num_declared_data_segments = 0; // From the DataCount section.
WireBytesRef name = {0, 0};
std::vector<FunctionSig*> signatures; // by signature index
std::vector<uint32_t> signature_ids; // by signature index

View File

@ -268,6 +268,13 @@ class TestModuleBuilder {
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; }
private:
@ -2738,17 +2745,19 @@ TEST_F(FunctionBodyDecoderTest, Regression709741) {
TEST_F(FunctionBodyDecoderTest, MemoryInit) {
TestModuleBuilder builder;
builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module();
EXPECT_FAILURE(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
WASM_FEATURE_SCOPE(bulk_memory);
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) {
TestModuleBuilder builder;
builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module();
WASM_FEATURE_SCOPE(bulk_memory);
@ -2760,10 +2769,15 @@ TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) {
}
TEST_F(FunctionBodyDecoderTest, MemoryDrop) {
TestModuleBuilder builder;
builder.InitializeMemory();
builder.SetDataSegmentCount(1);
module = builder.module();
EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(0));
WASM_FEATURE_SCOPE(bulk_memory);
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) {