Commit 8990399d authored by jbroman's avatar jbroman Committed by Commit bot

ValueDeserializer: Only allow valid keys when deserializing object properties.

The serializer won't ever write a more complex object. Not validating this
allows other things to be used as keys, and converted to string when the
property set actually occurs. It turns out this gives an opportunity to trigger
OOM by giving an object a key which is a very large sparse array (whose string
representation is very large).

This case is now rejected by the deserializer.

BUG=chromium:686511

Review-Url: https://codereview.chromium.org/2697023002
Cr-Commit-Position: refs/heads/master@{#43249}
parent 67544daa
......@@ -1657,6 +1657,10 @@ static void CommitProperties(Handle<JSObject> object, Handle<Map> map,
}
}
static bool IsValidObjectKey(Handle<Object> value) {
return value->IsName() || value->IsNumber();
}
Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
Handle<JSObject> object, SerializationTag end_tag,
bool can_use_transitions) {
......@@ -1692,7 +1696,9 @@ Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
key = expected_key;
target = TransitionArray::ExpectedTransitionTarget(map);
} else {
if (!ReadObject().ToHandle(&key)) return Nothing<uint32_t>();
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
return Nothing<uint32_t>();
}
if (key->IsString()) {
key =
isolate_->factory()->InternalizeString(Handle<String>::cast(key));
......@@ -1772,7 +1778,9 @@ Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
}
Handle<Object> key;
if (!ReadObject().ToHandle(&key)) return Nothing<uint32_t>();
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
return Nothing<uint32_t>();
}
Handle<Object> value;
if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>();
......@@ -1821,6 +1829,7 @@ static Maybe<bool> SetPropertiesFromKeyValuePairs(Isolate* isolate,
uint32_t num_properties) {
for (unsigned i = 0; i < 2 * num_properties; i += 2) {
Handle<Object> key = data[i];
if (!IsValidObjectKey(key)) return Nothing<bool>();
Handle<Object> value = data[i + 1];
bool success;
LookupIterator it = LookupIterator::PropertyOrElement(
......
......@@ -682,6 +682,14 @@ TEST_F(ValueSerializerTest, DecodeDictionaryObject) {
});
}
TEST_F(ValueSerializerTest, InvalidDecodeObjectWithInvalidKeyType) {
// Objects which would need conversion to string shouldn't be present as
// object keys. The serializer would have obtained them from the own property
// keys list, which should only contain names and indices.
InvalidDecodeTest(
{0xff, 0x09, 0x6f, 0x61, 0x00, 0x40, 0x00, 0x00, 0x7b, 0x01});
}
TEST_F(ValueSerializerTest, RoundTripOnlyOwnEnumerableStringKeys) {
// Only "own" properties should be serialized, not ones on the prototype.
RoundTripTest("(() => { var x = {}; x.__proto__ = {a: 4}; return x; })()",
......
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