Skip to content

Commit

Permalink
[CVE-2018-0936] Incorrect byte code for captured function expression …
Browse files Browse the repository at this point in the history
…name may lead to OOB - Internal
  • Loading branch information
pleath authored and akroshg committed Mar 12, 2018
1 parent 8b229ce commit 64e7619
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 49 deletions.
24 changes: 0 additions & 24 deletions lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,21 +932,6 @@ Symbol* Parser::AddDeclForPid(ParseNodePtr pnode, IdentPtr pid, SymbolType symbo
CheckRedeclarationErrorForBlockId(pid, pnodeFnc->sxFnc.pnodeScopes->sxBlock.blockId);
}

if ((scope->GetScopeType() == ScopeType_FunctionBody || scope->GetScopeType() == ScopeType_Parameter) && symbolType != STFunction)
{
AnalysisAssert(pnodeFnc);
if (pnodeFnc->sxFnc.pnodeName &&
pnodeFnc->sxFnc.pnodeName->nop == knopVarDecl &&
pnodeFnc->sxFnc.pnodeName->sxVar.pid == pid &&
(pnodeFnc->sxFnc.IsBodyAndParamScopeMerged() || scope->GetScopeType() == ScopeType_Parameter))
{
// Named function expression has its name hidden by a local declaration.
// This is important to know if we don't know whether nested deferred functions refer to it,
// because if the name has a non-local reference then we have to create a scope object.
m_currentNodeFunc->sxFnc.SetNameIsHidden();
}
}

if (!sym)
{
const char16 *name = reinterpret_cast<const char16*>(pid->Psz());
Expand Down Expand Up @@ -6576,15 +6561,6 @@ bool Parser::ParseFncNames(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, u
*pFncNamePid = pidBase;
}

if (fDeclaration &&
pnodeFncParent &&
pnodeFncParent->sxFnc.pnodeName &&
pnodeFncParent->sxFnc.pnodeName->nop == knopVarDecl &&
pnodeFncParent->sxFnc.pnodeName->sxVar.pid == pidBase)
{
pnodeFncParent->sxFnc.SetNameIsHidden();
}

if (buildAST)
{
AnalysisAssert(pnodeFnc);
Expand Down
5 changes: 1 addition & 4 deletions lib/Parser/ptree.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ enum FncFlags : uint
kFunctionIsClassConstructor = 1 << 18, // function is a class constructor
kFunctionIsBaseClassConstructor = 1 << 19, // function is a base class constructor
kFunctionIsClassMember = 1 << 20, // function is a class member
kFunctionNameIsHidden = 1 << 21, // True if a named function expression has its name hidden from nested functions
// Free = 1 << 21,
kFunctionIsGeneratedDefault = 1 << 22, // Is the function generated by us as a default (e.g. default class constructor)
kFunctionHasDefaultArguments = 1 << 23, // Function has one or more ES6 default arguments
kFunctionIsStaticMember = 1 << 24,
Expand Down Expand Up @@ -317,7 +317,6 @@ struct PnFnc
void SetIsLambda(bool set = true) { SetFlags(kFunctionIsLambda, set); }
void SetIsMethod(bool set = true) { SetFlags(kFunctionIsMethod, set); }
void SetIsStaticMember(bool set = true) { SetFlags(kFunctionIsStaticMember, set); }
void SetNameIsHidden(bool set = true) { SetFlags(kFunctionNameIsHidden, set); }
void SetNested(bool set = true) { SetFlags(kFunctionNested, set); }
void SetStrictMode(bool set = true) { SetFlags(kFunctionStrictMode, set); }
void SetIsModule(bool set = true) { SetFlags(kFunctionIsModule, set); }
Expand Down Expand Up @@ -358,7 +357,6 @@ struct PnFnc
bool IsNested() const { return HasFlags(kFunctionNested); }
bool IsStaticMember() const { return HasFlags(kFunctionIsStaticMember); }
bool IsModule() const { return HasFlags(kFunctionIsModule); }
bool NameIsHidden() const { return HasFlags(kFunctionNameIsHidden); }
bool UsesArguments() const { return HasFlags(kFunctionUsesArguments); }
bool IsDefaultModuleExport() const { return HasFlags(kFunctionIsDefaultModuleExport); }
bool NestedFuncEscapes() const { return nestedFuncEscapes; }
Expand All @@ -370,7 +368,6 @@ struct PnFnc
kFunctionNested |
kFunctionDeclaration |
kFunctionStrictMode |
kFunctionNameIsHidden |
kFunctionHasReferenceableBuiltInArguments |
kFunctionHasNonThisStmt |
// todo:: we shouldn't accept kFunctionHasAnyWriteToFormals on the asm module, but it looks like a bug is setting that flag incorrectly
Expand Down
23 changes: 4 additions & 19 deletions lib/Runtime/ByteCode/ByteCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2686,27 +2686,12 @@ FuncInfo* PostVisitFunction(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerat
Assert(CONFIG_FLAG(DeferNested));
byteCodeGenerator->ProcessCapturedSym(sym);

if (!top->root->sxFnc.NameIsHidden())
top->SetFuncExprNameReference(true);
if (pnode->sxFnc.pnodeBody)
{
top->SetFuncExprNameReference(true);
if (pnode->sxFnc.pnodeBody)
{
top->GetParsedFunctionBody()->SetFuncExprNameReference(true);
}
if (!sym->GetScope()->GetIsObject())
{
// The function expression symbol will be emitted in the param/body scope.
if (top->GetParamScope())
{
top->GetParamScope()->SetHasOwnLocalInClosure(true);
}
else
{
top->GetBodyScope()->SetHasOwnLocalInClosure(true);
}
top->SetHasLocalInClosure(true);
}
top->GetParsedFunctionBody()->SetFuncExprNameReference(true);
}
byteCodeGenerator->ProcessScopeWithCapturedSym(sym->GetScope());
}
}

Expand Down
1 change: 1 addition & 0 deletions test/Function/evenMoreFuncExpr3.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ obj[0].z : proto[0].z
obj[0].w : proto[0].w
obj[1].z : undefined
obj[1].w : undefined
pass
10 changes: 8 additions & 2 deletions test/Function/evenMoreFuncExpr3.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ var a = function x() {
"use strict";
x = 1;
};
}

};

(function __f_997(__v_4351 = function () {
WScript.Echo('pass');
return __f_997;
}()) {
function __f_997() {}
})();

0 comments on commit 64e7619

Please sign in to comment.