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