Commit 40dd0658 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[debugger] Properly deal with settled promises in catch prediction.

The catch prediction logic got confused when we merged the reactions and
result fields of JSPromise, because for settled promises it would start
to treat the result as reactions list, leading to a crash most likely or
memory corruption in the worst case (only if break on uncaught exception
is enabled). We can only inspect reactions when the promise is still in
"pending" state.

Bug: chromium:808973, v8:7253
Change-Id: I15162c96fce959a052fbc628addd9418da39327c
Reviewed-on: https://chromium-review.googlesource.com/903163Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51106}
parent ba330c3e
......@@ -2058,29 +2058,31 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
return true;
}
for (Handle<Object> current(promise->reactions(), isolate);
!current->IsSmi();) {
Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(current);
Handle<HeapObject> promise_or_capability(reaction->promise_or_capability(),
isolate);
Handle<JSPromise> promise = Handle<JSPromise>::cast(
promise_or_capability->IsJSPromise()
? promise_or_capability
: handle(Handle<PromiseCapability>::cast(promise_or_capability)
->promise(),
isolate));
if (reaction->reject_handler()->IsUndefined(isolate)) {
if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) {
return true;
}
} else {
Handle<JSReceiver> current_handler(
JSReceiver::cast(reaction->reject_handler()), isolate);
if (PromiseHandlerCheck(isolate, current_handler, promise)) {
return true;
if (promise->status() == Promise::kPending) {
for (Handle<Object> current(promise->reactions(), isolate);
!current->IsSmi();) {
Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(current);
Handle<HeapObject> promise_or_capability(
reaction->promise_or_capability(), isolate);
Handle<JSPromise> promise = Handle<JSPromise>::cast(
promise_or_capability->IsJSPromise()
? promise_or_capability
: handle(Handle<PromiseCapability>::cast(promise_or_capability)
->promise(),
isolate));
if (reaction->reject_handler()->IsUndefined(isolate)) {
if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) {
return true;
}
} else {
Handle<JSReceiver> current_handler(
JSReceiver::cast(reaction->reject_handler()), isolate);
if (PromiseHandlerCheck(isolate, current_handler, promise)) {
return true;
}
}
current = handle(reaction->next(), isolate);
}
current = handle(reaction->next(), isolate);
}
return false;
......
// Copyright 2018 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.
// Flags: --allow-natives-syntax --enable-inspector
const Debug = debug.Debug;
Debug.setListener(() => {});
Debug.setBreakOnUncaughtException()
function sleep() {
return new Promise(resolve => setTimeout(resolve, 1));
}
async function thrower() {
await sleep();
throw "a"; // Exception a
}
(async function() { thrower(); })();
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