Skip to content

Commit bf572c7

Browse files
addaleaxrefack
authored andcommitted
deps: V8: cherry-pick 91f0cd0
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 <[email protected]> Reviewed-by: Michael Starzinger <[email protected]> Reviewed-by: Adam Klein <[email protected]> Cr-Commit-Position: refs/heads/master@{#60075} Refs: v8/v8@91f0cd0 PR-URL: #26685 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Refael Ackermann <[email protected]>
1 parent 09f134f commit bf572c7

File tree

10 files changed

+105
-25
lines changed

10 files changed

+105
-25
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

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

4242
##### V8 defaults for Node.js #####
4343

deps/v8/include/v8.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -10939,7 +10939,11 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
1093910939
reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) +
1094010940
I::kExternalMemoryAtLastMarkCompactOffset);
1094110941

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

1094510949
int64_t allocation_diff_since_last_mc =

deps/v8/src/builtins/builtins-string.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,12 @@ BUILTIN(StringRaw) {
448448
Object::ToLength(isolate, raw_len));
449449

450450
IncrementalStringBuilder result_builder(isolate);
451-
const uint32_t length = static_cast<uint32_t>(raw_len->Number());
451+
// Intentional spec violation: we ignore {length} values >= 2^32, because
452+
// assuming non-empty chunks they would generate too-long strings anyway.
453+
const double raw_len_number = raw_len->Number();
454+
const uint32_t length = raw_len_number > std::numeric_limits<uint32_t>::max()
455+
? std::numeric_limits<uint32_t>::max()
456+
: static_cast<uint32_t>(raw_len_number);
452457
if (length > 0) {
453458
Handle<Object> first_element;
454459
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first_element,

deps/v8/src/builtins/builtins-typed-array.cc

+8-11
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,18 @@ BUILTIN(TypedArrayPrototypeBuffer) {
2727
namespace {
2828

2929
int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
30-
int64_t relative;
3130
if (V8_LIKELY(num->IsSmi())) {
32-
relative = Smi::ToInt(*num);
31+
int64_t relative = Smi::ToInt(*num);
32+
return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
33+
: std::min<int64_t>(relative, maximum);
3334
} else {
3435
DCHECK(num->IsHeapNumber());
35-
double fp = HeapNumber::cast(*num)->value();
36-
if (V8_UNLIKELY(!std::isfinite(fp))) {
37-
// +Infinity / -Infinity
38-
DCHECK(!std::isnan(fp));
39-
return fp < 0 ? minimum : maximum;
40-
}
41-
relative = static_cast<int64_t>(fp);
36+
double relative = HeapNumber::cast(*num)->value();
37+
DCHECK(!std::isnan(relative));
38+
return static_cast<int64_t>(
39+
relative < 0 ? std::max<double>(relative + maximum, minimum)
40+
: std::min<double>(relative, maximum));
4241
}
43-
return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
44-
: std::min<int64_t>(relative, maximum);
4542
}
4643

4744
} // namespace

deps/v8/src/compiler/representation-change.cc

+6-3
Original file line numberDiff line numberDiff line change
@@ -977,9 +977,12 @@ Node* RepresentationChanger::GetWord64RepresentationFor(
977977
break;
978978
case IrOpcode::kNumberConstant: {
979979
double const fv = OpParameter<double>(node->op());
980-
int64_t const iv = static_cast<int64_t>(fv);
981-
if (static_cast<double>(iv) == fv) {
982-
return jsgraph()->Int64Constant(iv);
980+
using limits = std::numeric_limits<int64_t>;
981+
if (fv <= limits::max() && fv >= limits::min()) {
982+
int64_t const iv = static_cast<int64_t>(fv);
983+
if (static_cast<double>(iv) == fv) {
984+
return jsgraph()->Int64Constant(iv);
985+
}
983986
}
984987
break;
985988
}

deps/v8/src/objects/bigint.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1875,7 +1875,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
18751875
bits_min = (bits_min + roundup) >> kBitsPerCharTableShift;
18761876
if (bits_min <= static_cast<size_t>(kMaxInt)) {
18771877
// Divide by kDigitsBits, rounding up.
1878-
int length = (static_cast<int>(bits_min) + kDigitBits - 1) / kDigitBits;
1878+
int length = static_cast<int>((bits_min + kDigitBits - 1) / kDigitBits);
18791879
if (length <= kMaxLength) {
18801880
Handle<MutableBigInt> result =
18811881
MutableBigInt::New(isolate, length, pretenure).ToHandleChecked();

deps/v8/src/objects/fixed-array-inl.h

+3
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,9 @@ inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
737737

738738
template <>
739739
inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
740+
using limits = std::numeric_limits<float>;
741+
if (value > limits::max()) return limits::infinity();
742+
if (value < limits::lowest()) return -limits::infinity();
740743
return static_cast<float>(value);
741744
}
742745

deps/v8/src/wasm/module-instantiate.cc

+19-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// found in the LICENSE file.
44

55
#include "src/wasm/module-instantiate.h"
6+
67
#include "src/asmjs/asm-js.h"
8+
#include "src/conversions-inl.h"
79
#include "src/heap/heap-inl.h" // For CodeSpaceMemoryModificationScope.
810
#include "src/property-descriptor.h"
911
#include "src/utils.h"
@@ -132,6 +134,7 @@ class InstanceBuilder {
132134
void LoadDataSegments(Handle<WasmInstanceObject> instance);
133135

134136
void WriteGlobalValue(const WasmGlobal& global, double value);
137+
void WriteGlobalValue(const WasmGlobal& global, int64_t num);
135138
void WriteGlobalValue(const WasmGlobal& global,
136139
Handle<WasmGlobalObject> value);
137140

@@ -653,25 +656,34 @@ void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
653656
switch (global.type) {
654657
case kWasmI32:
655658
WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
656-
static_cast<int32_t>(num));
659+
DoubleToInt32(num));
657660
break;
658661
case kWasmI64:
659-
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
660-
static_cast<int64_t>(num));
662+
// The Wasm-BigInt proposal currently says that i64 globals may
663+
// only be initialized with BigInts. See:
664+
// https://github.com/WebAssembly/JS-BigInt-integration/issues/12
665+
UNREACHABLE();
661666
break;
662667
case kWasmF32:
663668
WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
664-
static_cast<float>(num));
669+
DoubleToFloat32(num));
665670
break;
666671
case kWasmF64:
667-
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
668-
static_cast<double>(num));
672+
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
669673
break;
670674
default:
671675
UNREACHABLE();
672676
}
673677
}
674678

679+
void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, int64_t num) {
680+
TRACE("init [globals_start=%p + %u] = %" PRId64 ", type = %s\n",
681+
reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
682+
global.offset, num, ValueTypes::TypeName(global.type));
683+
DCHECK_EQ(kWasmI64, global.type);
684+
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
685+
}
686+
675687
void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
676688
Handle<WasmGlobalObject> value) {
677689
TRACE("init [globals_start=%p + %u] = ",
@@ -1051,7 +1063,7 @@ bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
10511063
return true;
10521064
}
10531065

1054-
if (value->IsNumber()) {
1066+
if (value->IsNumber() && global.type != kWasmI64) {
10551067
WriteGlobalValue(global, value->Number());
10561068
return true;
10571069
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2019 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
load('test/mjsunit/wasm/wasm-module-builder.js');
6+
7+
// crbug.com/933134
8+
(function() {
9+
var builder = new WasmModuleBuilder();
10+
builder.addImportedGlobal("mod", "i32", kWasmI32);
11+
builder.addImportedGlobal("mod", "f32", kWasmF32);
12+
var module = new WebAssembly.Module(builder.toBuffer());
13+
return new WebAssembly.Instance(module, {
14+
mod: {
15+
i32: 1e12,
16+
f32: 1e300,
17+
}
18+
});
19+
})();

deps/v8/test/mjsunit/ubsan-fuzzerbugs.js

+37
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// Flags: --allow-natives-syntax
6+
57
// crbug.com/923466
68
__v_5 = [ -1073741825, -2147483648];
79
__v_5.sort();
@@ -17,3 +19,38 @@ new Date(2148022800000).toString();
1719

1820
// crbug.com/927212
1921
assertThrows(() => (2n).toString(-2147483657), RangeError);
22+
23+
// crbug.com/927894
24+
var typed_array = new Uint8Array(16);
25+
typed_array.fill(0, -1.7976931348623157e+308);
26+
27+
// crbug.com/927996
28+
var float_array = new Float32Array(1);
29+
float_array[0] = 1e51;
30+
31+
// crbug.com/930086
32+
(function() {
33+
try {
34+
// Build up a 536870910-character string (just under 2**30).
35+
var string = "ff";
36+
var long_string = "0x";
37+
for (var i = 2; i < 29; i++) {
38+
string = string + string;
39+
long_string += string;
40+
}
41+
assertThrows(() => BigInt(long_string), SyntaxError);
42+
} catch (e) {
43+
/* 32-bit architectures have a lower string length limit. */
44+
}
45+
})();
46+
47+
// crbug.com/932679
48+
(function() {
49+
const buffer = new DataView(new ArrayBuffer(2));
50+
function __f_14159(buffer) {
51+
try { return buffer.getUint16(Infinity, true); } catch(e) { return 0; }
52+
}
53+
__f_14159(buffer);
54+
%OptimizeFunctionOnNextCall(__f_14159);
55+
__f_14159(buffer);
56+
})();

0 commit comments

Comments
 (0)