Skip to content

Commit

Permalink
[api] Fix empty Maybe crash in GetRealNamedPropertyAttributes
Browse files Browse the repository at this point in the history
`Object::GetRealNamedPropertyAttributes()` can crash if an empty
`Maybe` is returned by `JSReceiver::GetPropertyAttributes()` because
it was not checking for that. Fix that.

Refs: nodejs/node#34606
Change-Id: Ic83f904ba7134786bcd8f786eb2ce98adb4fea1e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2335057
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69258}
  • Loading branch information
addaleax authored and Commit Bot committed Aug 6, 2020
1 parent 6315167 commit e06ace6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
12 changes: 7 additions & 5 deletions src/api/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4728,9 +4728,9 @@ Maybe<PropertyAttribute>
v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
Local<Context> context, Local<Name> key) {
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
ENTER_V8_NO_SCRIPT(isolate, context, Object,
GetRealNamedPropertyAttributesInPrototypeChain,
Nothing<PropertyAttribute>(), i::HandleScope);
ENTER_V8(isolate, context, Object,
GetRealNamedPropertyAttributesInPrototypeChain,
Nothing<PropertyAttribute>(), i::HandleScope);
i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
if (!self->IsJSObject()) return Nothing<PropertyAttribute>();
i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
Expand All @@ -4743,6 +4743,7 @@ v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
Maybe<i::PropertyAttributes> result =
i::JSReceiver::GetPropertyAttributes(&it);
has_pending_exception = result.IsNothing();
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
if (!it.IsFound()) return Nothing<PropertyAttribute>();
if (result.FromJust() == i::ABSENT) return Just(None);
Expand All @@ -4767,14 +4768,15 @@ MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
Local<Context> context, Local<Name> key) {
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
ENTER_V8_NO_SCRIPT(isolate, context, Object, GetRealNamedPropertyAttributes,
Nothing<PropertyAttribute>(), i::HandleScope);
ENTER_V8(isolate, context, Object, GetRealNamedPropertyAttributes,
Nothing<PropertyAttribute>(), i::HandleScope);
i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
i::LookupIterator::Key lookup_key(isolate, key_obj);
i::LookupIterator it(isolate, self, lookup_key, self,
i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
auto result = i::JSReceiver::GetPropertyAttributes(&it);
has_pending_exception = result.IsNothing();
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute);
if (!it.IsFound()) return Nothing<PropertyAttribute>();
if (result.FromJust() == i::ABSENT) {
Expand Down
42 changes: 42 additions & 0 deletions test/cctest/test-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11985,6 +11985,48 @@ THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
CHECK(result.IsEmpty());
}

THREADED_TEST(GetRealNamedPropertyAttributes_With_Proxy) {
LocalContext context;
HandleScope scope(context->GetIsolate());

{
Local<Object> proxy =
CompileRun(
"new Proxy({ p: 1 }, { getOwnPropertyDescriptor: _ => { "
" throw new Error('xyz'); } });")
.As<Object>();
TryCatch try_catch(context->GetIsolate());
v8::Maybe<v8::PropertyAttribute> result =
proxy->GetRealNamedPropertyAttributes(context.local(), v8_str("p"));
CHECK(result.IsNothing());
CHECK(try_catch.HasCaught());
CHECK(try_catch.Exception()
.As<Object>()
->Get(context.local(), v8_str("message"))
.ToLocalChecked()
->StrictEquals(v8_str("xyz")));
}

{
Local<Object> proxy =
CompileRun(
"Object.create("
" new Proxy({ p: 1 }, { getOwnPropertyDescriptor: _ => { "
" throw new Error('abc'); } }))")
.As<Object>();
TryCatch try_catch(context->GetIsolate());
v8::Maybe<v8::PropertyAttribute> result =
proxy->GetRealNamedPropertyAttributesInPrototypeChain(context.local(),
v8_str("p"));
CHECK(result.IsNothing());
CHECK(try_catch.HasCaught());
CHECK(try_catch.Exception()
.As<Object>()
->Get(context.local(), v8_str("message"))
.ToLocalChecked()
->StrictEquals(v8_str("abc")));
}
}

static void ThrowingCallbackWithTryCatch(
const v8::FunctionCallbackInfo<v8::Value>& args) {
Expand Down

0 comments on commit e06ace6

Please sign in to comment.