Commit c249669c authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Add missing validation on Drop

Before dropping a value we should validate that there is indeed a value
on the stack.

R=jkummerow@chromium.org

Bug: chromium:1184964
Change-Id: Iec3ac061df2545717749e664b10c383765d67c9d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2739588Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73263}
parent 0fe9c835
...@@ -3084,6 +3084,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -3084,6 +3084,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
DECODE(Drop) { DECODE(Drop) {
Peek(0, 0);
CALL_INTERFACE_IF_REACHABLE(Drop); CALL_INTERFACE_IF_REACHABLE(Drop);
Drop(1); Drop(1);
return 1; return 1;
...@@ -4802,14 +4803,14 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -4802,14 +4803,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
V8_INLINE void Drop(int count = 1) { V8_INLINE void Drop(int count = 1) {
DCHECK(!control_.empty()); DCHECK(!control_.empty());
uint32_t limit = control_.back().stack_depth; uint32_t limit = control_.back().stack_depth;
// TODO(wasm): This check is often redundant.
if (V8_UNLIKELY(stack_size() < limit + count)) { if (V8_UNLIKELY(stack_size() < limit + count)) {
// Popping past the current control start in reachable code. // Popping past the current control start in reachable code.
if (!VALIDATE(!control_.back().reachable())) { if (!VALIDATE(!control_.back().reachable())) {
NotEnoughArgumentsError(0); NotEnoughArgumentsError(0);
} }
// Pop what we can. // Pop what we can.
stack_end_ -= std::min(count, static_cast<int>(stack_size() - limit)); count = std::min(count, static_cast<int>(stack_size() - limit));
return;
} }
DCHECK_LE(stack_, stack_end_ - count); DCHECK_LE(stack_, stack_end_ - count);
stack_end_ -= count; stack_end_ -= count;
......
// Copyright 2021 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-lazy-compilation
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction('foo', kSig_v_v).addBody([kExprDrop]);
assertThrows(() => builder.instantiate(), WebAssembly.CompileError);
...@@ -4365,6 +4365,16 @@ TEST_F(FunctionBodyDecoderTest, Regress_1154439) { ...@@ -4365,6 +4365,16 @@ TEST_F(FunctionBodyDecoderTest, Regress_1154439) {
ExpectFailure(sigs.v_v(), {}, kAppendEnd, "local count too large"); ExpectFailure(sigs.v_v(), {}, kAppendEnd, "local count too large");
} }
TEST_F(FunctionBodyDecoderTest, DropOnEmptyStack) {
// Valid code:
ExpectValidates(sigs.v_v(), {kExprI32Const, 1, kExprDrop}, kAppendEnd);
// Invalid code (dropping from empty stack):
ExpectFailure(sigs.v_v(), {kExprDrop}, kAppendEnd,
"not enough arguments on the stack for drop");
// Valid code (dropping from empty stack in unreachable code):
ExpectValidates(sigs.v_v(), {kExprUnreachable, kExprDrop}, kAppendEnd);
}
class BranchTableIteratorTest : public TestWithZone { class BranchTableIteratorTest : public TestWithZone {
public: public:
BranchTableIteratorTest() : TestWithZone() {} BranchTableIteratorTest() : TestWithZone() {}
......
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