Commit 85b4ec50 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Fix {StreamingDecoder} to reject multiple code sections.

R=ahaas@chromium.org
TEST=mjsunit/regress/wasm/regress-935138
BUG=chromium:935138

Change-Id: I73465e0edcdfcd33b96764ffaf5f33519e424bb8
Reviewed-on: https://chromium-review.googlesource.com/c/1486471
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59852}
parent fa07eba8
...@@ -393,6 +393,14 @@ StreamingDecoder::DecodeSectionLength::NextWithValue( ...@@ -393,6 +393,14 @@ StreamingDecoder::DecodeSectionLength::NextWithValue(
return base::make_unique<DecodeSectionID>(streaming->module_offset_); return base::make_unique<DecodeSectionID>(streaming->module_offset_);
} else { } else {
if (section_id_ == SectionCode::kCodeSectionCode) { if (section_id_ == SectionCode::kCodeSectionCode) {
// Explicitly check for multiple code sections as module decoder never
// sees the code section and hence cannot track this section.
if (streaming->code_section_processed_) {
// TODO(mstarzinger): This error message (and other in this class) is
// different for non-streaming decoding. Bring them in sync and test.
return streaming->Error("code section can only appear once");
}
streaming->code_section_processed_ = true;
// We reached the code section. All functions of the code section are put // We reached the code section. All functions of the code section are put
// into the same SectionBuffer. // into the same SectionBuffer.
return base::make_unique<DecodeNumberOfFunctions>(buf); return base::make_unique<DecodeNumberOfFunctions>(buf);
......
...@@ -261,6 +261,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder { ...@@ -261,6 +261,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder {
std::unique_ptr<StreamingProcessor> processor_; std::unique_ptr<StreamingProcessor> processor_;
std::unique_ptr<DecodingState> state_; std::unique_ptr<DecodingState> state_;
std::vector<std::shared_ptr<SectionBuffer>> section_buffers_; std::vector<std::shared_ptr<SectionBuffer>> section_buffers_;
bool code_section_processed_ = false;
uint32_t module_offset_ = 0; uint32_t module_offset_ = 0;
size_t total_size_ = 0; size_t total_size_ = 0;
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --wasm-test-streaming
load("test/mjsunit/wasm/wasm-module-builder.js");
(function TestAsyncCompileMultipleCodeSections() {
let binary = new Binary();
binary.emit_header();
binary.push(kTypeSectionCode, 4, 1, kWasmFunctionTypeForm, 0, 0);
binary.push(kFunctionSectionCode, 2, 1, 0);
binary.push(kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd);
binary.push(kCodeSectionCode, 6, 1, 4, 0, kExprGetLocal, 0, kExprEnd);
let buffer = Uint8Array.from(binary).buffer;
assertPromiseResult(WebAssembly.compile(buffer), assertUnreachable,
e => assertInstanceof(e, WebAssembly.CompileError));
})();
...@@ -52,26 +52,12 @@ class MockStreamingProcessor : public StreamingProcessor { ...@@ -52,26 +52,12 @@ class MockStreamingProcessor : public StreamingProcessor {
// Process all sections but the code section. // Process all sections but the code section.
bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes, bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes,
uint32_t offset) override { uint32_t offset) override {
// Mock a simple processor that rejects non-consecutive section codes.
if (section_code != kUnknownSectionCode) {
if (section_code < next_section_) {
result_->error = WasmError(0, "section out of order");
return false;
}
next_section_ = section_code + 1;
}
++result_->num_sections; ++result_->num_sections;
return true; return true;
} }
bool ProcessCodeSectionHeader(size_t num_functions, uint32_t offset, bool ProcessCodeSectionHeader(size_t num_functions, uint32_t offset,
std::shared_ptr<WireBytesStorage>) override { std::shared_ptr<WireBytesStorage>) override {
// Mock a simple processor that rejects non-consecutive section codes.
if (kCodeSectionCode < next_section_) {
result_->error = WasmError(0, "section out of order");
return false;
}
next_section_ = kCodeSectionCode + 1;
return true; return true;
} }
...@@ -104,7 +90,6 @@ class MockStreamingProcessor : public StreamingProcessor { ...@@ -104,7 +90,6 @@ class MockStreamingProcessor : public StreamingProcessor {
private: private:
MockStreamingResult* const result_; MockStreamingResult* const result_;
uint8_t next_section_ = kFirstSectionInModule;
}; };
class WasmStreamingDecoderTest : public ::testing::Test { class WasmStreamingDecoderTest : public ::testing::Test {
...@@ -624,7 +609,7 @@ TEST_F(WasmStreamingDecoderTest, TwoCodeSections) { ...@@ -624,7 +609,7 @@ TEST_F(WasmStreamingDecoderTest, TwoCodeSections) {
0x1, // Function Length 0x1, // Function Length
0x0, // Function 0x0, // Function
}; };
ExpectFailure(ArrayVector(data), "section out of order"); ExpectFailure(ArrayVector(data), "code section can only appear once");
} }
TEST_F(WasmStreamingDecoderTest, UnknownSection) { TEST_F(WasmStreamingDecoderTest, UnknownSection) {
...@@ -665,7 +650,7 @@ TEST_F(WasmStreamingDecoderTest, UnknownSectionSandwich) { ...@@ -665,7 +650,7 @@ TEST_F(WasmStreamingDecoderTest, UnknownSectionSandwich) {
0x1, // Function Length 0x1, // Function Length
0x0, // Function 0x0, // Function
}; };
ExpectFailure(ArrayVector(data), "section out of order"); ExpectFailure(ArrayVector(data), "code section can only appear once");
} }
} // namespace wasm } // namespace wasm
......
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