Skip to content

Commit

Permalink
deps: V8: cherry-pick 91f0cd0
Browse files Browse the repository at this point in the history
Original commit message:

    [ubsan] Fix various ClusterFuzz-found issues

    Fixing a few float and int overflows.
    Drive-by fix: with --experimental-wasm-bigint, Number values
    may not be used to initialize i64-typed globals. The existing
    code for doing that relied on UB; since it's a spec violation
    the fix is to throw instead.

    No regression test for 933103 because it will OOM anyway.
    No regression test for 932896 because it would be extremely slow.

    Bug: chromium:927894, chromium:927996, chromium:930086, chromium:932679, chromium:932896, chromium:933103, chromium:933134
    Change-Id: Iae1c1ff1038af4512a52d3e56b8c4b75f2233314
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1495911
    Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
    Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
    Reviewed-by: Adam Klein <adamk@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#60075}

Refs: v8/v8@91f0cd0

PR-URL: #26685
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
  • Loading branch information
addaleax authored and refack committed Mar 28, 2019
1 parent 09f134f commit bf572c7
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 25 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.2',
'v8_embedder_string': '-node.3',

##### V8 defaults for Node.js #####

Expand Down
6 changes: 5 additions & 1 deletion deps/v8/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -10939,7 +10939,11 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) +
I::kExternalMemoryAtLastMarkCompactOffset);

const int64_t amount = *external_memory + change_in_bytes;
// Embedders are weird: we see both over- and underflows here. Perform the
// addition with unsigned types to avoid undefined behavior.
const int64_t amount =
static_cast<int64_t>(static_cast<uint64_t>(change_in_bytes) +
static_cast<uint64_t>(*external_memory));
*external_memory = amount;

int64_t allocation_diff_since_last_mc =
Expand Down
7 changes: 6 additions & 1 deletion deps/v8/src/builtins/builtins-string.cc
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,12 @@ BUILTIN(StringRaw) {
Object::ToLength(isolate, raw_len));

IncrementalStringBuilder result_builder(isolate);
const uint32_t length = static_cast<uint32_t>(raw_len->Number());
// Intentional spec violation: we ignore {length} values >= 2^32, because
// assuming non-empty chunks they would generate too-long strings anyway.
const double raw_len_number = raw_len->Number();
const uint32_t length = raw_len_number > std::numeric_limits<uint32_t>::max()
? std::numeric_limits<uint32_t>::max()
: static_cast<uint32_t>(raw_len_number);
if (length > 0) {
Handle<Object> first_element;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first_element,
Expand Down
19 changes: 8 additions & 11 deletions deps/v8/src/builtins/builtins-typed-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,18 @@ BUILTIN(TypedArrayPrototypeBuffer) {
namespace {

int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
int64_t relative;
if (V8_LIKELY(num->IsSmi())) {
relative = Smi::ToInt(*num);
int64_t relative = Smi::ToInt(*num);
return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
: std::min<int64_t>(relative, maximum);
} else {
DCHECK(num->IsHeapNumber());
double fp = HeapNumber::cast(*num)->value();
if (V8_UNLIKELY(!std::isfinite(fp))) {
// +Infinity / -Infinity
DCHECK(!std::isnan(fp));
return fp < 0 ? minimum : maximum;
}
relative = static_cast<int64_t>(fp);
double relative = HeapNumber::cast(*num)->value();
DCHECK(!std::isnan(relative));
return static_cast<int64_t>(
relative < 0 ? std::max<double>(relative + maximum, minimum)
: std::min<double>(relative, maximum));
}
return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
: std::min<int64_t>(relative, maximum);
}

} // namespace
Expand Down
9 changes: 6 additions & 3 deletions deps/v8/src/compiler/representation-change.cc
Original file line number Diff line number Diff line change
Expand Up @@ -977,9 +977,12 @@ Node* RepresentationChanger::GetWord64RepresentationFor(
break;
case IrOpcode::kNumberConstant: {
double const fv = OpParameter<double>(node->op());
int64_t const iv = static_cast<int64_t>(fv);
if (static_cast<double>(iv) == fv) {
return jsgraph()->Int64Constant(iv);
using limits = std::numeric_limits<int64_t>;
if (fv <= limits::max() && fv >= limits::min()) {
int64_t const iv = static_cast<int64_t>(fv);
if (static_cast<double>(iv) == fv) {
return jsgraph()->Int64Constant(iv);
}
}
break;
}
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/objects/bigint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1875,7 +1875,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
bits_min = (bits_min + roundup) >> kBitsPerCharTableShift;
if (bits_min <= static_cast<size_t>(kMaxInt)) {
// Divide by kDigitsBits, rounding up.
int length = (static_cast<int>(bits_min) + kDigitBits - 1) / kDigitBits;
int length = static_cast<int>((bits_min + kDigitBits - 1) / kDigitBits);
if (length <= kMaxLength) {
Handle<MutableBigInt> result =
MutableBigInt::New(isolate, length, pretenure).ToHandleChecked();
Expand Down
3 changes: 3 additions & 0 deletions deps/v8/src/objects/fixed-array-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {

template <>
inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
using limits = std::numeric_limits<float>;
if (value > limits::max()) return limits::infinity();
if (value < limits::lowest()) return -limits::infinity();
return static_cast<float>(value);
}

Expand Down
26 changes: 19 additions & 7 deletions deps/v8/src/wasm/module-instantiate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// found in the LICENSE file.

#include "src/wasm/module-instantiate.h"

#include "src/asmjs/asm-js.h"
#include "src/conversions-inl.h"
#include "src/heap/heap-inl.h" // For CodeSpaceMemoryModificationScope.
#include "src/property-descriptor.h"
#include "src/utils.h"
Expand Down Expand Up @@ -132,6 +134,7 @@ class InstanceBuilder {
void LoadDataSegments(Handle<WasmInstanceObject> instance);

void WriteGlobalValue(const WasmGlobal& global, double value);
void WriteGlobalValue(const WasmGlobal& global, int64_t num);
void WriteGlobalValue(const WasmGlobal& global,
Handle<WasmGlobalObject> value);

Expand Down Expand Up @@ -653,25 +656,34 @@ void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
switch (global.type) {
case kWasmI32:
WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
static_cast<int32_t>(num));
DoubleToInt32(num));
break;
case kWasmI64:
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
static_cast<int64_t>(num));
// The Wasm-BigInt proposal currently says that i64 globals may
// only be initialized with BigInts. See:
// https://github.com/WebAssembly/JS-BigInt-integration/issues/12
UNREACHABLE();
break;
case kWasmF32:
WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
static_cast<float>(num));
DoubleToFloat32(num));
break;
case kWasmF64:
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
static_cast<double>(num));
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
break;
default:
UNREACHABLE();
}
}

void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, int64_t num) {
TRACE("init [globals_start=%p + %u] = %" PRId64 ", type = %s\n",
reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
global.offset, num, ValueTypes::TypeName(global.type));
DCHECK_EQ(kWasmI64, global.type);
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
}

void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
Handle<WasmGlobalObject> value) {
TRACE("init [globals_start=%p + %u] = ",
Expand Down Expand Up @@ -1051,7 +1063,7 @@ bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
return true;
}

if (value->IsNumber()) {
if (value->IsNumber() && global.type != kWasmI64) {
WriteGlobalValue(global, value->Number());
return true;
}
Expand Down
19 changes: 19 additions & 0 deletions deps/v8/test/mjsunit/regress/wasm/regress-ubsan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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.

load('test/mjsunit/wasm/wasm-module-builder.js');

// crbug.com/933134
(function() {
var builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "i32", kWasmI32);
builder.addImportedGlobal("mod", "f32", kWasmF32);
var module = new WebAssembly.Module(builder.toBuffer());
return new WebAssembly.Instance(module, {
mod: {
i32: 1e12,
f32: 1e300,
}
});
})();
37 changes: 37 additions & 0 deletions deps/v8/test/mjsunit/ubsan-fuzzerbugs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --allow-natives-syntax

// crbug.com/923466
__v_5 = [ -1073741825, -2147483648];
__v_5.sort();
Expand All @@ -17,3 +19,38 @@ new Date(2148022800000).toString();

// crbug.com/927212
assertThrows(() => (2n).toString(-2147483657), RangeError);

// crbug.com/927894
var typed_array = new Uint8Array(16);
typed_array.fill(0, -1.7976931348623157e+308);

// crbug.com/927996
var float_array = new Float32Array(1);
float_array[0] = 1e51;

// crbug.com/930086
(function() {
try {
// Build up a 536870910-character string (just under 2**30).
var string = "ff";
var long_string = "0x";
for (var i = 2; i < 29; i++) {
string = string + string;
long_string += string;
}
assertThrows(() => BigInt(long_string), SyntaxError);
} catch (e) {
/* 32-bit architectures have a lower string length limit. */
}
})();

// crbug.com/932679
(function() {
const buffer = new DataView(new ArrayBuffer(2));
function __f_14159(buffer) {
try { return buffer.getUint16(Infinity, true); } catch(e) { return 0; }
}
__f_14159(buffer);
%OptimizeFunctionOnNextCall(__f_14159);
__f_14159(buffer);
})();

0 comments on commit bf572c7

Please sign in to comment.