summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael BrĂ¼ning <michael.bruning@qt.io>2020-01-14 12:58:22 +0100
committerMichael BrĂ¼ning <michael.bruning@qt.io>2020-01-16 13:08:43 +0000
commitc68e3faa08f985b6c212eac65b9f4de8ed24ca98 (patch)
tree8050eb6bee799ad87a80ed0f48be206620431a6c
parent5e753a5b1d72fb30f955ab482196b0f1a533769f (diff)
downloadqtwebengine-chromium-c68e3faa08f985b6c212eac65b9f4de8ed24ca98.tar.gz
[Backport] CVE-2019-13735: Out of bounds write in V8
Manual backport of patch: Merged: Squashed multiple commits. Merged: Ensure root maps do not have slack in descriptor array Revision: 31fab144f0652a6aa1f284b60655300ed746b2b6 Merged: Properly share descriptor arrays Revision: f53c728f55f61deeeacbf669d6aff726244ea5fe Merged: Fix too restrictive check in Map::MapVerify Revision: e34e5271d954f7d7e4f87c4c7ab867b3c8e6d891 BUG=chromium:1025468,chromium:1027498,chromium:1028396 NOTRY=true NOPRESUBMIT=true NOTREECHECKS=true R=verwaest@chromium.org Cr-Branched-From: be181e241c6da9baa49a424b7d91613c8ebf76f8-refs/heads/7.9.317@{#1} Cr-Branched-From: 0d7889d0b14939fa5c09c39a0a5eb155b74163e4-refs/heads/master@{#64307 Change-Id: I8b1cd3a94ab60fae3a1108726e780110fdc6bc3d Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--chromium/v8/BUILD.gn4
-rw-r--r--chromium/v8/src/diagnostics/objects-debug.cc29
-rw-r--r--chromium/v8/src/heap/factory.cc13
-rw-r--r--chromium/v8/src/objects/map.cc28
4 files changed, 57 insertions, 17 deletions
diff --git a/chromium/v8/BUILD.gn b/chromium/v8/BUILD.gn
index e21400265dd..e8b042d58cb 100644
--- a/chromium/v8/BUILD.gn
+++ b/chromium/v8/BUILD.gn
@@ -1248,6 +1248,10 @@ template("run_mksnapshot") {
args += [ "--no-enable-slow-asserts" ]
}
}
+
+ if (v8_enable_verify_heap) {
+ args += [ "--verify-heap" ]
+ }
}
}
diff --git a/chromium/v8/src/diagnostics/objects-debug.cc b/chromium/v8/src/diagnostics/objects-debug.cc
index dc3b3b8091c..07634f3ca79 100644
--- a/chromium/v8/src/diagnostics/objects-debug.cc
+++ b/chromium/v8/src/diagnostics/objects-debug.cc
@@ -656,8 +656,33 @@ void Map::MapVerify(Isolate* isolate) {
CHECK(instance_size() == kVariableSizeSentinel ||
(kTaggedSize <= instance_size() &&
static_cast<size_t>(instance_size()) < heap->Capacity()));
- CHECK(GetBackPointer().IsUndefined(isolate) ||
- !Map::cast(GetBackPointer()).is_stable());
+ if (GetBackPointer().IsUndefined(isolate)) {
+ // Root maps must not have descriptors in the descriptor array that do not
+ // belong to the map.
+ CHECK_EQ(NumberOfOwnDescriptors(),
+ instance_descriptors().number_of_descriptors());
+ } else {
+ // If there is a parent map it must be non-stable.
+ Map parent = Map::cast(GetBackPointer());
+ CHECK(!parent.is_stable());
+ DescriptorArray descriptors = instance_descriptors();
+ if (descriptors == parent.instance_descriptors()) {
+ if (NumberOfOwnDescriptors() == parent.NumberOfOwnDescriptors() + 1) {
+ // Descriptors sharing through property transitions takes over
+ // ownership from the parent map.
+ CHECK(!parent.owns_descriptors());
+ } else {
+ CHECK_EQ(NumberOfOwnDescriptors(), parent.NumberOfOwnDescriptors());
+ // Descriptors sharing through special transitions properly takes over
+ // ownership from the parent map unless it uses the canonical empty
+ // descriptor array.
+ if (descriptors != ReadOnlyRoots(isolate).empty_descriptor_array()) {
+ CHECK_IMPLIES(owns_descriptors(), !parent.owns_descriptors());
+ CHECK_IMPLIES(parent.owns_descriptors(), !owns_descriptors());
+ }
+ }
+ }
+ }
SLOW_DCHECK(instance_descriptors().IsSortedNoDuplicates());
DisallowHeapAllocation no_gc;
SLOW_DCHECK(
diff --git a/chromium/v8/src/heap/factory.cc b/chromium/v8/src/heap/factory.cc
index 19c36656225..679dc555870 100644
--- a/chromium/v8/src/heap/factory.cc
+++ b/chromium/v8/src/heap/factory.cc
@@ -4027,6 +4027,7 @@ Handle<Map> Factory::CreateSloppyFunctionMap(
map->AppendDescriptor(isolate(), &d);
}
DCHECK_EQ(inobject_properties_count, field_index);
+ DCHECK_EQ(0, map->instance_descriptors().number_of_slack_descriptors());
LOG(isolate(), MapDetails(*map));
return map;
}
@@ -4037,10 +4038,15 @@ Handle<Map> Factory::CreateStrictFunctionMap(
int header_size = has_prototype ? JSFunction::kSizeWithPrototype
: JSFunction::kSizeWithoutPrototype;
int inobject_properties_count = 0;
- if (IsFunctionModeWithName(function_mode)) ++inobject_properties_count;
+ // length and prototype accessors or just length accessor.
+ int descriptors_count = IsFunctionModeWithPrototype(function_mode) ? 2 : 1;
+ if (IsFunctionModeWithName(function_mode)) {
+ ++inobject_properties_count; // name property.
+ } else {
+ ++descriptors_count; // name accessor.
+ }
if (IsFunctionModeWithHomeObject(function_mode)) ++inobject_properties_count;
- int descriptors_count = (IsFunctionModeWithPrototype(function_mode) ? 3 : 2) +
- inobject_properties_count;
+ descriptors_count += inobject_properties_count;
Handle<Map> map = NewMap(
JS_FUNCTION_TYPE, header_size + inobject_properties_count * kTaggedSize,
@@ -4104,6 +4110,7 @@ Handle<Map> Factory::CreateStrictFunctionMap(
map->AppendDescriptor(isolate(), &d);
}
DCHECK_EQ(inobject_properties_count, field_index);
+ DCHECK_EQ(0, map->instance_descriptors().number_of_slack_descriptors());
LOG(isolate(), MapDetails(*map));
return map;
}
diff --git a/chromium/v8/src/objects/map.cc b/chromium/v8/src/objects/map.cc
index 7b4f1abd05f..632fbd8a25a 100644
--- a/chromium/v8/src/objects/map.cc
+++ b/chromium/v8/src/objects/map.cc
@@ -644,9 +644,8 @@ Map Map::FindRootMap(Isolate* isolate) const {
while (true) {
Object back = result.GetBackPointer(isolate);
if (back.IsUndefined(isolate)) {
- // Initial map always owns descriptors and doesn't have unused entries
- // in the descriptor array.
- DCHECK(result.owns_descriptors());
+ // Initial map must not contain descriptors in the descriptors array
+ // that do not belong to the map.
DCHECK_EQ(result.NumberOfOwnDescriptors(),
result.instance_descriptors().number_of_descriptors());
return result;
@@ -1575,9 +1574,8 @@ void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
*map == *isolate->async_function_with_home_object_map() ||
*map == *isolate->async_function_with_name_and_home_object_map());
#endif
- // Initial maps must always own their descriptors and it's descriptor array
- // does not contain descriptors that do not belong to the map.
- DCHECK(map->owns_descriptors());
+ // Initial maps must not contain descriptors in the descriptors array
+ // that do not belong to the map.
DCHECK_EQ(map->NumberOfOwnDescriptors(),
map->instance_descriptors().number_of_descriptors());
}
@@ -1595,6 +1593,11 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
int instance_size, int inobject_properties,
int unused_property_fields) {
EnsureInitialMap(isolate, map);
+ // Initial map must not contain descriptors in the descriptors array
+ // that do not belong to the map.
+ DCHECK_EQ(map->NumberOfOwnDescriptors(),
+ map->instance_descriptors().number_of_descriptors());
+
Handle<Map> result =
RawCopy(isolate, map, instance_size, inobject_properties);
@@ -1603,9 +1606,10 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
if (number_of_own_descriptors > 0) {
- // The copy will use the same descriptors array.
- result->UpdateDescriptors(isolate, map->instance_descriptors(),
- map->GetLayoutDescriptor(),
+ // The copy will use the same descriptors array without ownership.
+ DescriptorArray descriptors = map->instance_descriptors();
+ result->set_owns_descriptors(false);
+ result->UpdateDescriptors(isolate, descriptors, map->GetLayoutDescriptor(),
number_of_own_descriptors);
DCHECK_EQ(result->NumberOfFields(),
@@ -1685,9 +1689,8 @@ void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
if (!parent->GetBackPointer().IsUndefined(isolate)) {
parent->set_owns_descriptors(false);
} else {
- // |parent| is initial map and it must keep the ownership, there must be no
- // descriptors in the descriptors array that do not belong to the map.
- DCHECK(parent->owns_descriptors());
+ // |parent| is initial map and it must not contain descriptors in the
+ // descriptors array that do not belong to the map.
DCHECK_EQ(parent->NumberOfOwnDescriptors(),
parent->instance_descriptors().number_of_descriptors());
}
@@ -1924,6 +1927,7 @@ Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
// In case the map owned its own descriptors, share the descriptors and
// transfer ownership to the new map.
// The properties did not change, so reuse descriptors.
+ map->set_owns_descriptors(false);
new_map->InitializeDescriptors(isolate, map->instance_descriptors(),
map->GetLayoutDescriptor());
} else {