Просмотр исходного кода

[CVE-2018-0936] Incorrect byte code for captured function expression name may lead to OOB - Internal

Paul Leathers 8 лет назад
Родитель
Сommit
64e761923d

+ 0 - 24
lib/Parser/Parse.cpp

@@ -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());
@@ -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);

+ 1 - 4
lib/Parser/ptree.h

@@ -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,
@@ -317,7 +317,6 @@ public:
     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); }
@@ -358,7 +357,6 @@ public:
     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; }
@@ -370,7 +368,6 @@ public:
         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

+ 4 - 19
lib/Runtime/ByteCode/ByteCodeGenerator.cpp

@@ -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());
         }
     }
 

+ 1 - 0
test/Function/evenMoreFuncExpr3.baseline

@@ -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

+ 8 - 2
test/Function/evenMoreFuncExpr3.js

@@ -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() {}
+})();