mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
Bug 1454285 - Part 2: Disallow using innermostEmitterScope while the value does not match the bytecode environment.
Tag #1287
This commit is contained in:
parent
85d4d59f04
commit
d16b90c099
2 changed files with 76 additions and 32 deletions
|
|
@ -100,7 +100,7 @@ class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::Nestab
|
|||
NestableControl(BytecodeEmitter* bce, StatementKind kind)
|
||||
: Nestable<NestableControl>(&bce->innermostNestableControl),
|
||||
kind_(kind),
|
||||
emitterScope_(bce->innermostEmitterScope)
|
||||
emitterScope_(bce->innermostEmitterScopeNoCheck())
|
||||
{ }
|
||||
|
||||
public:
|
||||
|
|
@ -426,7 +426,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
|
|||
// enclosing BCE.
|
||||
if ((*bce)->parent) {
|
||||
*bce = (*bce)->parent;
|
||||
return (*bce)->innermostEmitterScope;
|
||||
return (*bce)->innermostEmitterScopeNoCheck();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
@ -460,7 +460,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
|
|||
|
||||
public:
|
||||
explicit EmitterScope(BytecodeEmitter* bce)
|
||||
: Nestable<EmitterScope>(&bce->innermostEmitterScope),
|
||||
: Nestable<EmitterScope>(&bce->innermostEmitterScope_),
|
||||
nameCache_(bce->cx->frontendCollectionPool()),
|
||||
hasEnvironment_(false),
|
||||
environmentChainLength_(0),
|
||||
|
|
@ -866,7 +866,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
|
|||
Handle<LexicalScope::Data*> bindings)
|
||||
{
|
||||
MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
if (!ensureCache(bce))
|
||||
return false;
|
||||
|
|
@ -935,7 +935,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
MOZ_ASSERT(funbox->namedLambdaBindings());
|
||||
|
||||
if (!ensureCache(bce))
|
||||
|
|
@ -1002,7 +1002,7 @@ BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce,
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
if (!ensureCache(bce))
|
||||
return false;
|
||||
|
|
@ -1035,7 +1035,7 @@ BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
// If there are parameter expressions, there is an extra var scope.
|
||||
if (!funbox->hasExtraBodyVarScope())
|
||||
|
|
@ -1126,7 +1126,7 @@ BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, F
|
|||
MOZ_ASSERT(funbox->hasParameterExprs);
|
||||
MOZ_ASSERT(funbox->extraVarScopeBindings() ||
|
||||
funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings());
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
// The extra var scope is never popped once it's entered. It replaces the
|
||||
// function scope as the var emitter scope.
|
||||
|
|
@ -1212,7 +1212,7 @@ class DynamicBindingIter : public BindingIter
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
bce->setVarEmitterScope(this);
|
||||
|
||||
|
|
@ -1272,7 +1272,7 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
bce->setVarEmitterScope(this);
|
||||
|
||||
|
|
@ -1327,7 +1327,7 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
bce->setVarEmitterScope(this);
|
||||
|
||||
|
|
@ -1384,7 +1384,7 @@ BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedCon
|
|||
bool
|
||||
BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
|
||||
{
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
if (!ensureCache(bce))
|
||||
return false;
|
||||
|
|
@ -1412,7 +1412,7 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
|
|||
{
|
||||
// If we aren't leaving the scope due to a non-local jump (e.g., break),
|
||||
// we must be the innermost scope.
|
||||
MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope);
|
||||
MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
ScopeKind kind = scope(bce)->kind();
|
||||
switch (kind) {
|
||||
|
|
@ -2123,7 +2123,7 @@ class ForOfLoopControl : public LoopControl
|
|||
|
||||
bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce,
|
||||
CompletionKind completionKind = CompletionKind::Normal) {
|
||||
return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind);
|
||||
return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(), completionKind);
|
||||
}
|
||||
|
||||
bool emitIteratorCloseInScope(BytecodeEmitter* bce,
|
||||
|
|
@ -2201,8 +2201,11 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
|
|||
bodyScopeIndex(UINT32_MAX),
|
||||
varEmitterScope(nullptr),
|
||||
innermostNestableControl(nullptr),
|
||||
innermostEmitterScope(nullptr),
|
||||
innermostEmitterScope_(nullptr),
|
||||
innermostTDZCheckCache(nullptr),
|
||||
#ifdef DEBUG
|
||||
unstableEmitterScope(false),
|
||||
#endif
|
||||
constList(cx),
|
||||
scopeList(cx),
|
||||
tryNoteList(cx),
|
||||
|
|
@ -2259,13 +2262,13 @@ BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
|
|||
NameLocation
|
||||
BytecodeEmitter::lookupName(JSAtom* name)
|
||||
{
|
||||
return innermostEmitterScope->lookup(this, name);
|
||||
return innermostEmitterScope()->lookup(this, name);
|
||||
}
|
||||
|
||||
Maybe<NameLocation>
|
||||
BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
|
||||
{
|
||||
return innermostEmitterScope->locationBoundInScope(this, name, target);
|
||||
return innermostEmitterScope()->locationBoundInScope(this, name, target);
|
||||
}
|
||||
|
||||
Maybe<NameLocation>
|
||||
|
|
@ -2726,7 +2729,7 @@ class NonLocalExitControl
|
|||
: bce_(bce),
|
||||
savedScopeNoteIndex_(bce->scopeNoteList.length()),
|
||||
savedDepth_(bce->stackDepth),
|
||||
openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex()),
|
||||
openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
|
||||
kind_(kind)
|
||||
{ }
|
||||
|
||||
|
|
@ -2772,9 +2775,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta
|
|||
using NestableControl = BytecodeEmitter::NestableControl;
|
||||
using EmitterScope = BytecodeEmitter::EmitterScope;
|
||||
|
||||
EmitterScope* es = bce_->innermostEmitterScope;
|
||||
EmitterScope* es = bce_->innermostEmitterScope();
|
||||
int npops = 0;
|
||||
|
||||
AutoCheckUnstableEmitterScope cues(bce_);
|
||||
|
||||
// For 'continue', 'break', and 'return' statements, emit IteratorClose
|
||||
// bytecode inline. 'continue' statements do not call IteratorClose for
|
||||
// the loop they are continuing.
|
||||
|
|
@ -2895,7 +2900,7 @@ BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteTy
|
|||
Scope*
|
||||
BytecodeEmitter::innermostScope() const
|
||||
{
|
||||
return innermostEmitterScope->scope(this);
|
||||
return innermostEmitterScope()->scope(this);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -3555,7 +3560,7 @@ BytecodeEmitter::needsImplicitThis()
|
|||
return true;
|
||||
|
||||
// Otherwise see if the current point is under a 'with'.
|
||||
for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) {
|
||||
for (EmitterScope* es = innermostEmitterScope(); es; es = es->enclosingInFrame()) {
|
||||
if (es->scope(this)->kind() == ScopeKind::With)
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5206,7 +5211,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri
|
|||
// destructuring declaration needs to initialize the name in
|
||||
// the function scope. The innermost scope is the var scope,
|
||||
// and its enclosing scope is the function scope.
|
||||
EmitterScope* funScope = innermostEmitterScope->enclosingInFrame();
|
||||
EmitterScope* funScope = innermostEmitterScope()->enclosingInFrame();
|
||||
NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope);
|
||||
if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true))
|
||||
return false;
|
||||
|
|
@ -7308,7 +7313,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
// bindings inducing an environment, recreate the current environment.
|
||||
DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
|
||||
MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
||||
if (headLexicalEmitterScope->hasEnvironment()) {
|
||||
|
|
@ -7490,7 +7495,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
|
|||
// it must be the innermost one. If that scope has closed-over
|
||||
// bindings inducing an environment, recreate the current environment.
|
||||
MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
||||
if (headLexicalEmitterScope->hasEnvironment()) {
|
||||
|
|
@ -7619,7 +7624,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
// exists for the head, it must be the innermost one. If that scope
|
||||
// has closed-over bindings inducing an environment, recreate the
|
||||
// current environment.
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
||||
if (headLexicalEmitterScope->hasEnvironment()) {
|
||||
|
|
@ -7667,7 +7672,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
|
||||
// ES 13.7.4.8 step 3.e. The per-iteration freshening.
|
||||
if (forLoopRequiresFreshening) {
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
||||
if (headLexicalEmitterScope->hasEnvironment()) {
|
||||
|
|
@ -10367,7 +10372,7 @@ BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
|
|||
{
|
||||
ParseNode* funBody = pn->last();
|
||||
FunctionBox* funbox = sc->asFunctionBox();
|
||||
EmitterScope* funScope = innermostEmitterScope;
|
||||
EmitterScope* funScope = innermostEmitterScope();
|
||||
|
||||
bool hasParameterExprs = funbox->hasParameterExprs;
|
||||
bool hasRest = funbox->hasRest();
|
||||
|
|
|
|||
|
|
@ -228,9 +228,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
EmitterScope* varEmitterScope;
|
||||
NestableControl* innermostNestableControl;
|
||||
EmitterScope* innermostEmitterScope;
|
||||
EmitterScope* innermostEmitterScope_;
|
||||
TDZCheckCache* innermostTDZCheckCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool unstableEmitterScope;
|
||||
|
||||
friend class AutoCheckUnstableEmitterScope;
|
||||
#endif
|
||||
|
||||
EmitterScope* innermostEmitterScope() const {
|
||||
MOZ_ASSERT(!unstableEmitterScope);
|
||||
return innermostEmitterScopeNoCheck();
|
||||
}
|
||||
EmitterScope* innermostEmitterScopeNoCheck() const {
|
||||
return innermostEmitterScope_;
|
||||
}
|
||||
|
||||
CGConstList constList; /* constants to be included with the script */
|
||||
CGObjectList objectList; /* list of emitted objects */
|
||||
CGScopeList scopeList; /* list of emitted scopes */
|
||||
|
|
@ -319,7 +333,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
EmitterScope* source);
|
||||
|
||||
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(JSAtom* name) {
|
||||
return locationOfNameBoundInFunctionScope(name, innermostEmitterScope);
|
||||
return locationOfNameBoundInFunctionScope(name, innermostEmitterScope());
|
||||
}
|
||||
|
||||
void setVarEmitterScope(EmitterScope* emitterScope) {
|
||||
|
|
@ -610,7 +624,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitToIteratorResult(bool done);
|
||||
|
||||
MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() {
|
||||
return emitGetDotGeneratorInScope(*innermostEmitterScope);
|
||||
return emitGetDotGeneratorInScope(*innermostEmitterScope());
|
||||
}
|
||||
MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope);
|
||||
|
||||
|
|
@ -619,7 +633,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitYieldOp(JSOp op);
|
||||
MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
|
||||
MOZ_MUST_USE bool emitAwaitInInnermostScope() {
|
||||
return emitAwaitInScope(*innermostEmitterScope);
|
||||
return emitAwaitInScope(*innermostEmitterScope());
|
||||
}
|
||||
MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope);
|
||||
|
|
@ -729,7 +743,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync,
|
||||
CompletionKind completionKind = CompletionKind::Normal,
|
||||
bool allowSelfHosted = false) {
|
||||
return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind,
|
||||
return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, completionKind,
|
||||
allowSelfHosted);
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +843,31 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoCheckUnstableEmitterScope {
|
||||
#ifdef DEBUG
|
||||
bool prev_;
|
||||
BytecodeEmitter* bce_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
AutoCheckUnstableEmitterScope() = delete;
|
||||
explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce)
|
||||
#ifdef DEBUG
|
||||
: bce_(bce)
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG
|
||||
prev_ = bce_->unstableEmitterScope;
|
||||
bce_->unstableEmitterScope = true;
|
||||
#endif
|
||||
}
|
||||
~AutoCheckUnstableEmitterScope() {
|
||||
#ifdef DEBUG
|
||||
bce_->unstableEmitterScope = prev_;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue