[x64] Check negative displacement of min int32_t
With a displacement of int32_t min (-2^31), and a displacement mode of kNegativeDisplacement, we will try to negate this constant, but the result will not fit in an int32_t, leading to a runtime crash. Check for this special case in CanBeImmediate, and return false. Bug: chromium:1091892 Change-Id: I7f18153d13805f2836dd5c8e1bc098f1e9600566 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2341095 Commit-Queue: Zhi An Ng <zhin@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Bill Budge <bbudge@chromium.org> Cr-Commit-Position: refs/heads/master@{#69311}
This commit is contained in:
parent
242df3a2ed
commit
2fe9406998
@ -25,8 +25,12 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
bool CanBeImmediate(Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kInt32Constant:
|
||||
case IrOpcode::kRelocatableInt32Constant:
|
||||
return true;
|
||||
case IrOpcode::kRelocatableInt32Constant: {
|
||||
const int32_t value = OpParameter<int32_t>(node->op());
|
||||
// int32_t min will overflow if displacement mode is
|
||||
// kNegativeDisplacement.
|
||||
return value != std::numeric_limits<int32_t>::min();
|
||||
}
|
||||
case IrOpcode::kInt64Constant: {
|
||||
const int64_t value = OpParameter<int64_t>(node->op());
|
||||
return std::numeric_limits<int32_t>::min() < value &&
|
||||
|
@ -2,10 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
|
||||
#include <limits>
|
||||
|
||||
#include "src/compiler/node-matchers.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -976,6 +977,37 @@ TEST_F(InstructionSelectorTest, Int32AddScaled2Other) {
|
||||
EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
|
||||
}
|
||||
|
||||
TEST_F(InstructionSelectorTest, Int32AddMinNegativeDisplacement) {
|
||||
// This test case is simplified from a Wasm fuzz test in
|
||||
// https://crbug.com/1091892. The key here is that we match on a
|
||||
// sequence like: Int32Add(Int32Sub(-524288, -2147483648), -26048), which
|
||||
// matches on an EmitLea, with -2147483648 as the displacement. Since we
|
||||
// have a Int32Sub node, it sets kNegativeDisplacement, and later we try to
|
||||
// negate -2147483648, which overflows.
|
||||
StreamBuilder m(this, MachineType::Int32());
|
||||
Node* const c0 = m.Int32Constant(-524288);
|
||||
Node* const c1 = m.Int32Constant(std::numeric_limits<int32_t>::min());
|
||||
Node* const c2 = m.Int32Constant(-26048);
|
||||
Node* const a0 = m.Int32Sub(c0, c1);
|
||||
Node* const a1 = m.Int32Add(a0, c2);
|
||||
m.Return(a1);
|
||||
Stream s = m.Build();
|
||||
ASSERT_EQ(2U, s.size());
|
||||
|
||||
EXPECT_EQ(kX64Sub32, s[0]->arch_opcode());
|
||||
ASSERT_EQ(2U, s[0]->InputCount());
|
||||
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
|
||||
EXPECT_EQ(s.ToVreg(c0), s.ToVreg(s[0]->InputAt(0)));
|
||||
EXPECT_EQ(s.ToVreg(c1), s.ToVreg(s[0]->InputAt(1)));
|
||||
EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
|
||||
|
||||
EXPECT_EQ(kX64Add32, s[1]->arch_opcode());
|
||||
ASSERT_EQ(2U, s[1]->InputCount());
|
||||
EXPECT_EQ(kMode_None, s[1]->addressing_mode());
|
||||
EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(0)));
|
||||
EXPECT_TRUE(s[1]->InputAt(1)->IsImmediate());
|
||||
EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Multiplication.
|
||||
|
Loading…
Reference in New Issue
Block a user