summaryrefslogtreecommitdiffstats
path: root/js/src/vm
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-25 18:21:15 +0200
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-25 18:21:15 +0200
commit05441d12b6bbc9dde268914fcfd374db61b83462 (patch)
tree87443cdcba99085f3a878e9e3a796ef8c3215bbc /js/src/vm
parent727c27a30d10a811d5a3fe04e2407cd7b3993b5e (diff)
downloadUXP-05441d12b6bbc9dde268914fcfd374db61b83462.tar
UXP-05441d12b6bbc9dde268914fcfd374db61b83462.tar.gz
UXP-05441d12b6bbc9dde268914fcfd374db61b83462.tar.lz
UXP-05441d12b6bbc9dde268914fcfd374db61b83462.tar.xz
UXP-05441d12b6bbc9dde268914fcfd374db61b83462.zip
Bug 1346862 - Fix IteratorClose due to non-local jumps being catchable by try statements inside for-of
Issue #74
Diffstat (limited to 'js/src/vm')
-rw-r--r--js/src/vm/Interpreter.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index eb3000e07..d20e5284d 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1156,6 +1156,7 @@ enum HandleErrorContinuation
static HandleErrorContinuation
ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
{
+ bool inForOfIterClose = false;
for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
@@ -1164,10 +1165,38 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
/* Catch cannot intercept the closing of a generator. */
if (cx->isClosingGenerator())
break;
+
+ // If IteratorClose due to abnormal completion threw inside a
+ // for-of loop, it is not catchable by try statements inside of
+ // the for-of loop.
+ //
+ // This is handled by this weirdness in the exception handler
+ // instead of in bytecode because it is hard to do so in bytecode:
+ //
+ // 1. IteratorClose emitted due to abnormal completion (break,
+ // throw, return) are emitted inline, at the source location of
+ // the break, throw, or return statement. For example:
+ //
+ // for (x of iter) {
+ // try { return; } catch (e) { }
+ // }
+ //
+ // From the try-note nesting's perspective, the IteratorClose
+ // resulting from |return| is covered by the inner try, when it
+ // should not be.
+ //
+ // 2. Try-catch notes cannot be disjoint. That is, we can't have
+ // multiple notes with disjoint pc ranges jumping to the same
+ // catch block.
+ if (inForOfIterClose)
+ break;
SettleOnTryNote(cx, tn, ei, regs);
return CatchContinuation;
case JSTRY_FINALLY:
+ // See note above.
+ if (inForOfIterClose)
+ break;
SettleOnTryNote(cx, tn, ei, regs);
return FinallyContinuation;
@@ -1206,7 +1235,14 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
break;
}
+ case JSTRY_FOR_OF_ITERCLOSE:
+ inForOfIterClose = true;
+ break;
+
case JSTRY_FOR_OF:
+ inForOfIterClose = false;
+ break;
+
case JSTRY_LOOP:
break;