summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartok <martok@martoks-place.de>2023-04-09 19:56:58 +0200
committerMartok <martok@martoks-place.de>2023-05-01 17:16:18 +0200
commit98853c14d7ac07ad046395c600b93f3eda444919 (patch)
tree2656e3d3e7580caedc8aa7feec582ab73684f1dd
parente708a68921c44c396502fda9849078f8b983f343 (diff)
downloaduxp-98853c14d7ac07ad046395c600b93f3eda444919.tar.gz
Issue #2142 - Restrict contents of direct eval in fields
Based-on: m-c 1542406
-rw-r--r--js/src/frontend/Parser.cpp24
-rw-r--r--js/src/frontend/Parser.h5
-rw-r--r--js/src/vm/Scope.cpp15
-rw-r--r--js/src/vm/Scope.h12
4 files changed, 42 insertions, 14 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index bd7dc40bf7..bc60503b25 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -214,12 +214,18 @@ SharedContext::computeAllowSyntax(Scope* scope)
{
for (ScopeIter si(scope); si; si++) {
if (si.kind() == ScopeKind::Function) {
- JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
+ FunctionScope* funScope = &si.scope()->as<FunctionScope>();
+ JSFunction* fun = funScope->canonicalFunction();
if (fun->isArrow())
continue;
allowNewTarget_ = true;
allowSuperProperty_ = fun->allowSuperProperty();
allowSuperCall_ = fun->isDerivedClassConstructor();
+ if (funScope->isFieldInitializer()) {
+ allowSuperProperty_ = false;
+ allowSuperCall_ = false;
+ allowArguments_ = false;
+ }
return;
}
}
@@ -1881,7 +1887,8 @@ Parser<FullParseHandler>::newEvalScopeData(ParseContext::Scope& scope)
template <>
Maybe<FunctionScope::Data*>
-Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool hasParameterExprs)
+Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool hasParameterExprs,
+ bool isFieldInitializer)
{
Vector<BindingName> positionalFormals(context);
Vector<BindingName> formals(context);
@@ -1955,6 +1962,8 @@ Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool
if (!bindings)
return Nothing();
+ bindings->isFieldInitializer = isFieldInitializer;
+
// The ordering here is important. See comments in FunctionScope.
BindingName* start = bindings->trailingNames.start();
BindingName* cursor = start;
@@ -2403,7 +2412,8 @@ Parser<ParseHandler>::finishFunctionScopes(bool isStandaloneFunction)
template <>
bool
-Parser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
+Parser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */,
+ bool isFieldInitializer /* = false */)
{
if (!finishFunctionScopes(isStandaloneFunction))
return false;
@@ -2420,7 +2430,8 @@ Parser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */
{
Maybe<FunctionScope::Data*> bindings = newFunctionScopeData(pc->functionScope(),
- hasParameterExprs);
+ hasParameterExprs,
+ isFieldInitializer);
if (!bindings)
return false;
funbox->functionScopeBindings().set(*bindings);
@@ -2438,7 +2449,8 @@ Parser<FullParseHandler>::finishFunction(bool isStandaloneFunction /* = false */
template <>
bool
-Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false */)
+Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false */,
+ bool isFieldInitializer /* = false */)
{
// The LazyScript for a lazily parsed function needs to know its set of
// free variables and inner functions so that when it is fully parsed, we
@@ -8076,7 +8088,7 @@ Parser<ParseHandler>::fieldInitializerOpt(YieldHandling yieldHandling, bool hasH
handler.setFunctionBody(funNode, initializerBody);
- if (!finishFunction())
+ if (!finishFunction(false, true))
return null();
if (!leaveInnerFunction(outerpc))
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index f29d5aaeed..5222d6398c 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -1572,7 +1572,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
bool tryAnnexB,
Directives inheritedDirectives, Directives* newDirectives);
bool finishFunctionScopes(bool isStandaloneFunction);
- bool finishFunction(bool isStandaloneFunction = false);
+ bool finishFunction(bool isStandaloneFunction = false, bool isFieldInitializer = false);
bool leaveInnerFunction(ParseContext* outerpc);
bool matchOrInsertSemicolonHelper(TokenStream::Modifier modifier);
@@ -1620,7 +1620,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
mozilla::Maybe<ModuleScope::Data*> newModuleScopeData(ParseContext::Scope& scope);
mozilla::Maybe<EvalScope::Data*> newEvalScopeData(ParseContext::Scope& scope);
mozilla::Maybe<FunctionScope::Data*> newFunctionScopeData(ParseContext::Scope& scope,
- bool hasParameterExprs);
+ bool hasParameterExprs,
+ bool isFieldInitializer);
mozilla::Maybe<VarScope::Data*> newVarScopeData(ParseContext::Scope& scope);
mozilla::Maybe<LexicalScope::Data*> newLexicalScopeData(ParseContext::Scope& scope);
LexicalScopeNodeType finishLexicalScope(ParseContext::Scope& scope, Node body);
diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
index 5cb9abaecf..870add219f 100644
--- a/js/src/vm/Scope.cpp
+++ b/js/src/vm/Scope.cpp
@@ -610,12 +610,14 @@ FunctionScope::create(ExclusiveContext* cx, Handle<Data*> dataArg,
if (!data)
return nullptr;
- return createWithData(cx, &data, hasParameterExprs, needsEnvironment, fun, enclosing);
+ return createWithData(cx, &data, hasParameterExprs, dataArg ? dataArg->isFieldInitializer : false,
+ needsEnvironment, fun, enclosing);
}
/* static */ FunctionScope*
FunctionScope::createWithData(ExclusiveContext* cx, MutableHandle<UniquePtr<Data>> data,
- bool hasParameterExprs, bool needsEnvironment,
+ bool hasParameterExprs, bool isFieldInitializer,
+ bool needsEnvironment,
HandleFunction fun, HandleScope enclosing)
{
MOZ_ASSERT(data);
@@ -636,6 +638,7 @@ FunctionScope::createWithData(ExclusiveContext* cx, MutableHandle<UniquePtr<Data
return nullptr;
}
+ data->isFieldInitializer = isFieldInitializer;
data->hasParameterExprs = hasParameterExprs;
data->canonicalFunction.init(fun);
@@ -737,16 +740,20 @@ FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosin
uint8_t needsEnvironment;
uint8_t hasParameterExprs;
+ uint8_t isFieldInitializer;
uint32_t nextFrameSlot;
if (mode == XDR_ENCODE) {
needsEnvironment = scope->hasEnvironment();
hasParameterExprs = data->hasParameterExprs;
+ isFieldInitializer = data->isFieldInitializer;
nextFrameSlot = data->nextFrameSlot;
}
if (!xdr->codeUint8(&needsEnvironment))
return false;
if (!xdr->codeUint8(&hasParameterExprs))
return false;
+ if (!xdr->codeUint8(&isFieldInitializer))
+ return false;
if (!xdr->codeUint16(&data->nonPositionalFormalStart))
return false;
if (!xdr->codeUint16(&data->varStart))
@@ -761,8 +768,8 @@ FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosin
MOZ_ASSERT(!data->nextFrameSlot);
}
- scope.set(createWithData(cx, &uniqueData.ref(), hasParameterExprs, needsEnvironment, fun,
- enclosing));
+ scope.set(createWithData(cx, &uniqueData.ref(), hasParameterExprs, !!isFieldInitializer,
+ needsEnvironment, fun, enclosing));
if (!scope)
return false;
diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
index fc1419bb89..a1e52e3800 100644
--- a/js/src/vm/Scope.h
+++ b/js/src/vm/Scope.h
@@ -500,6 +500,9 @@ class FunctionScope : public Scope
// bindings.
bool hasParameterExprs = false;
+ // Anonymous functions used in field initializers are limited.
+ bool isFieldInitializer = false;
+
// Bindings are sorted by kind in both frames and environments.
//
// Positional formal parameter names are those that are not
@@ -548,8 +551,9 @@ class FunctionScope : public Scope
private:
static FunctionScope* createWithData(ExclusiveContext* cx, MutableHandle<UniquePtr<Data>> data,
- bool hasParameterExprs, bool needsEnvironment,
- HandleFunction fun, HandleScope enclosing);
+ bool hasParameterExprs, bool isFieldInitializer,
+ bool needsEnvironment, HandleFunction fun,
+ HandleScope enclosing);
Data& data() {
return *reinterpret_cast<Data*>(data_);
@@ -574,6 +578,10 @@ class FunctionScope : public Scope
return data().hasParameterExprs;
}
+ bool isFieldInitializer() const {
+ return data().isFieldInitializer;
+ }
+
uint32_t numPositionalFormalParameters() const {
return data().nonPositionalFormalStart;
}