Never freeze/seal/preventExtensions objects with interceptors

BUG=v8:6163
R=verwaest@chromium.org

Change-Id: Ieaec78c806cc3d459488a8491e77b7b5a8047079
Reviewed-on: https://chromium-review.googlesource.com/461903
Commit-Queue: Jochen Eisinger <jochen@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44228}
This commit is contained in:
Jochen Eisinger 2017-03-29 13:03:38 +02:00 committed by Commit Bot
parent 1cbda23565
commit f8deca1c86
9 changed files with 72 additions and 11 deletions

View File

@ -4599,8 +4599,8 @@ Maybe<bool> v8::Object::SetIntegrityLevel(Local<Context> context,
auto self = Utils::OpenHandle(this);
i::JSReceiver::IntegrityLevel i_level =
level == IntegrityLevel::kFrozen ? i::FROZEN : i::SEALED;
Maybe<bool> result =
i::JSReceiver::SetIntegrityLevel(self, i_level, i::Object::DONT_THROW);
Maybe<bool> result = i::JSReceiver::SetIntegrityLevel(
self, i_level, i::Object::THROW_ON_ERROR);
has_pending_exception = result.IsNothing();
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return result;

View File

@ -280,8 +280,10 @@ class ErrorUtils : public AllStatic {
T(CallSiteMethod, "CallSite method % expects CallSite as receiver") \
T(CannotConvertToPrimitive, "Cannot convert object to primitive value") \
T(CannotPreventExt, "Cannot prevent extensions") \
T(CannotFreeze, "Cannot freeze") \
T(CannotFreezeArrayBufferView, \
"Cannot freeze array buffer views with elements") \
T(CannotSeal, "Cannot seal") \
T(CircularStructure, "Converting circular structure to JSON") \
T(ConstructAbstractClass, "Abstract class % not directly constructable") \
T(ConstAssign, "Assignment to constant variable.") \

View File

@ -7541,6 +7541,12 @@ Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
should_throw);
}
if (object->map()->has_named_interceptor() ||
object->map()->has_indexed_interceptor()) {
RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kCannotPreventExt));
}
if (!object->HasFixedTypedArrayElements()) {
// If there are fast elements we normalize.
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
@ -7701,6 +7707,25 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
}
if (object->map()->has_named_interceptor() ||
object->map()->has_indexed_interceptor()) {
MessageTemplate::Template message = MessageTemplate::kNone;
switch (attrs) {
case NONE:
message = MessageTemplate::kCannotPreventExt;
break;
case SEALED:
message = MessageTemplate::kCannotSeal;
break;
case FROZEN:
message = MessageTemplate::kCannotFreeze;
break;
}
RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
}
Handle<SeededNumberDictionary> new_element_dictionary;
if (!object->HasFixedTypedArrayElements() &&
!object->HasDictionaryElements() &&

View File

@ -217,7 +217,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(12),
B(LdaConstant), U8(11),
B(Star), R(13),
@ -701,7 +701,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(12),
B(LdaConstant), U8(11),
B(Star), R(13),
@ -1219,7 +1219,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(12),
B(LdaConstant), U8(11),
B(Star), R(13),
@ -1627,7 +1627,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(11),
B(LdaConstant), U8(10),
B(Star), R(12),

View File

@ -85,7 +85,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
@ -226,7 +226,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(13),
B(LdaConstant), U8(8),
B(Star), R(14),
@ -380,7 +380,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
@ -524,7 +524,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(11),
B(LdaConstant), U8(10),
B(Star), R(12),

View File

@ -493,7 +493,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Wide), B(LdaSmi), I16(132),
B(Star), R(11),
B(LdaConstant), U8(10),
B(Star), R(12),

View File

@ -12,6 +12,7 @@ v8_executable("unittests") {
"../../testing/gtest-support.h",
"api/access-check-unittest.cc",
"api/exception-unittest.cc",
"api/interceptor-unittest.cc",
"api/isolate-unittest.cc",
"api/remote-object-unittest.cc",
"api/v8-object-unittest.cc",

View File

@ -0,0 +1,32 @@
// Copyright 2017 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.
#include "include/v8.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace {
using InterceptorTest = TestWithContext;
void NamedGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {}
TEST_F(InterceptorTest, FreezeApiObjectWithInterceptor) {
TryCatch try_catch(isolate());
Local<FunctionTemplate> tmpl = FunctionTemplate::New(isolate());
tmpl->InstanceTemplate()->SetHandler(
NamedPropertyHandlerConfiguration(NamedGetter));
Local<Function> ctor = tmpl->GetFunction(context()).ToLocalChecked();
Local<Object> obj = ctor->NewInstance(context()).ToLocalChecked();
ASSERT_TRUE(
obj->SetIntegrityLevel(context(), IntegrityLevel::kFrozen).IsNothing());
ASSERT_TRUE(try_catch.HasCaught());
}
} // namespace
} // namespace v8

View File

@ -10,6 +10,7 @@
'unittests_sources': [ ### gcmole(all) ###
'api/access-check-unittest.cc',
'api/exception-unittest.cc',
'api/interceptor-unittest.cc',
'api/isolate-unittest.cc',
'api/remote-object-unittest.cc',
'api/v8-object-unittest.cc',