Commit 624bc966 authored by adamk's avatar adamk Committed by Commit bot

Super property loads and stores should throw if [[Prototype]] is null

While fixing the bug, removed code duplication from super load/store
runtime calls, and inlined calls of Object::ReadAbsentProperty (left
over from strong mode).

BUG=v8:5335

Review-Url: https://codereview.chromium.org/2311413002
Cr-Commit-Position: refs/heads/master@{#39257}
parent 279bc509
......@@ -995,12 +995,12 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
case LookupIterator::ACCESSOR:
return GetPropertyWithAccessor(it);
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return ReadAbsentProperty(it);
return it->isolate()->factory()->undefined_value();
case LookupIterator::DATA:
return it->GetDataValue();
}
}
return ReadAbsentProperty(it);
return it->isolate()->factory()->undefined_value();
}
......@@ -1349,7 +1349,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
Object::DONT_THROW);
Handle<Object> result = args.Call(call_fun, name);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (result.is_null()) return ReadAbsentProperty(isolate, receiver, name);
if (result.is_null()) return isolate->factory()->undefined_value();
// Rebox handle before return.
return handle(*result, isolate);
}
......@@ -1366,7 +1366,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
receiver, Handle<JSReceiver>::cast(getter));
}
// Getter is not a function.
return ReadAbsentProperty(isolate, receiver, it->GetName());
return isolate->factory()->undefined_value();
}
// static
......@@ -4819,17 +4819,6 @@ Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
}
MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it) {
return it->isolate()->factory()->undefined_value();
}
MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
Handle<Object> receiver,
Handle<Object> name) {
return isolate->factory()->undefined_value();
}
Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
Handle<Object> receiver,
Handle<Object> name,
......
......@@ -1317,10 +1317,6 @@ class Object {
LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
StoreFromKeyed store_mode);
MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty(
LookupIterator* it);
MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty(
Isolate* isolate, Handle<Object> receiver, Handle<Object> name);
MUST_USE_RESULT static Maybe<bool> CannotCreateProperty(
Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
Handle<Object> value, ShouldThrow should_throw);
......
......@@ -187,52 +187,65 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
end_position));
}
namespace {
static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
Handle<Object> receiver,
Handle<JSObject> home_object,
Handle<Name> name) {
enum class SuperMode { kLoad, kStore };
MaybeHandle<JSReceiver> GetSuperHolder(
Isolate* isolate, Handle<Object> receiver, Handle<JSObject> home_object,
SuperMode mode, MaybeHandle<Name> maybe_name, uint32_t index) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayAccess(handle(isolate->context()), home_object)) {
isolate->ReportFailedAccessCheck(home_object);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, JSReceiver);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) {
return Object::ReadAbsentProperty(isolate, proto, name);
MessageTemplate::Template message =
mode == SuperMode::kLoad ? MessageTemplate::kNonObjectPropertyLoad
: MessageTemplate::kNonObjectPropertyStore;
Handle<Name> name;
if (!maybe_name.ToHandle(&name)) {
name = isolate->factory()->Uint32ToString(index);
}
THROW_NEW_ERROR(isolate, NewTypeError(message, name, proto), JSReceiver);
}
return Handle<JSReceiver>::cast(proto);
}
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
MaybeHandle<Object> LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
Handle<JSObject> home_object,
Handle<Name> name) {
Handle<JSReceiver> holder;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, holder,
GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad, name, 0),
Object);
LookupIterator it(receiver, name, holder);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
return result;
}
static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
Handle<Object> receiver,
Handle<JSObject> home_object,
uint32_t index) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayAccess(handle(isolate->context()), home_object)) {
isolate->ReportFailedAccessCheck(home_object);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) {
Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
return Object::ReadAbsentProperty(isolate, proto, name);
}
LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
Handle<Object> receiver,
Handle<JSObject> home_object,
uint32_t index) {
Handle<JSReceiver> holder;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, holder,
GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad,
MaybeHandle<Name>(), index),
Object);
LookupIterator it(isolate, receiver, index, holder);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
return result;
}
} // anonymous namespace
RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
HandleScope scope(isolate);
......@@ -272,50 +285,43 @@ RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
LoadFromSuper(isolate, receiver, home_object, name));
}
namespace {
static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, LanguageMode language_mode) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayAccess(handle(isolate->context()), home_object)) {
isolate->ReportFailedAccessCheck(home_object);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
MaybeHandle<Object> StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Name> name,
Handle<Object> value,
LanguageMode language_mode) {
Handle<JSReceiver> holder;
ASSIGN_RETURN_ON_EXCEPTION(isolate, holder,
GetSuperHolder(isolate, receiver, home_object,
SuperMode::kStore, name, 0),
Object);
LookupIterator it(receiver, name, holder);
MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
Object::CERTAINLY_NOT_STORE_FROM_KEYED),
isolate->heap()->exception());
return *value;
MaybeHandle<Object>());
return value;
}
static Object* StoreElementToSuper(Isolate* isolate,
Handle<JSObject> home_object,
Handle<Object> receiver, uint32_t index,
Handle<Object> value,
LanguageMode language_mode) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayAccess(handle(isolate->context()), home_object)) {
isolate->ReportFailedAccessCheck(home_object);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
MaybeHandle<Object> StoreElementToSuper(Isolate* isolate,
Handle<JSObject> home_object,
Handle<Object> receiver, uint32_t index,
Handle<Object> value,
LanguageMode language_mode) {
Handle<JSReceiver> holder;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, holder,
GetSuperHolder(isolate, receiver, home_object, SuperMode::kStore,
MaybeHandle<Name>(), index),
Object);
LookupIterator it(isolate, receiver, index, holder);
MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode,
Object::MAY_BE_STORE_FROM_KEYED),
isolate->heap()->exception());
return *value;
MaybeHandle<Object>());
return value;
}
} // anonymous namespace
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
HandleScope scope(isolate);
......@@ -325,7 +331,8 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, STRICT);
RETURN_RESULT_OR_FAILURE(isolate, StoreToSuper(isolate, home_object, receiver,
name, value, STRICT));
}
......@@ -337,14 +344,13 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY);
RETURN_RESULT_OR_FAILURE(isolate, StoreToSuper(isolate, home_object, receiver,
name, value, SLOPPY));
}
static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Object> key,
Handle<Object> value,
LanguageMode language_mode) {
static MaybeHandle<Object> StoreKeyedToSuper(
Isolate* isolate, Handle<JSObject> home_object, Handle<Object> receiver,
Handle<Object> key, Handle<Object> value, LanguageMode language_mode) {
uint32_t index = 0;
if (key->ToArrayIndex(&index)) {
......@@ -352,8 +358,8 @@ static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
language_mode);
}
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Object::ToName(isolate, key));
ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
Object);
// TODO(verwaest): Unify using LookupIterator.
if (name->AsArrayIndex(&index)) {
return StoreElementToSuper(isolate, home_object, receiver, index, value,
......@@ -372,7 +378,9 @@ RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) {
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT);
RETURN_RESULT_OR_FAILURE(
isolate,
StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT));
}
......@@ -384,7 +392,9 @@ RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY);
RETURN_RESULT_OR_FAILURE(
isolate,
StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY));
}
......
......@@ -2213,3 +2213,35 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestNullSuperPropertyLoad() {
var obj = {
__proto__: null,
named() { return super.x },
keyed() { return super[5] }
};
assertThrows(obj.named, TypeError);
assertThrows(obj.keyed, TypeError);
class C extends null {
named() { return super.x }
keyed() { return super[5] }
}
assertThrows(C.prototype.named, TypeError);
assertThrows(C.prototype.keyed, TypeError);
})();
(function TestNullSuperPropertyStore() {
var obj = {
__proto__: null,
named() { super.x = 42 },
keyed() { super[5] = 42 }
};
assertThrows(obj.named, TypeError);
assertThrows(obj.keyed, TypeError);
class C extends null {
named() { super.x = 42 }
keyed() { super[5] = 42 }
}
assertThrows(C.prototype.named, TypeError);
assertThrows(C.prototype.keyed, TypeError);
})();
......@@ -493,12 +493,6 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=5334
'built-ins/Proxy/setPrototypeOf/internals-call-order': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5335
'language/expressions/super/prop-expr-cls-null-proto': [FAIL],
'language/expressions/super/prop-expr-obj-null-proto': [FAIL],
'language/expressions/super/prop-dot-cls-null-proto': [FAIL],
'language/expressions/super/prop-dot-obj-null-proto': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5336
'language/expressions/super/call-proto-not-ctor': [FAIL],
......
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