Browse Source

[CVE-2017-0138] fix issue with ExtraArg not being accounted correctly in stackwalker

Michael Holman 9 năm trước cách đây
mục cha
commit
1750d475e2

+ 3 - 3
lib/Runtime/Base/Debug.cpp

@@ -32,16 +32,16 @@ WCHAR* DumpCallStackFull(uint frameCount, bool print)
             Js::JavascriptFunction *jsFunc = walker.GetCurrentFunction();
 
             Js::FunctionBody * jsBody = jsFunc->GetFunctionBody();
-            Js::CallInfo const * callInfo = walker.GetCallInfo();
+            const Js::CallInfo callInfo = walker.GetCallInfo();
             const WCHAR* sourceFileName = _u("NULL");
             ULONG line = 0; LONG column = 0;
             walker.GetSourcePosition(&sourceFileName, &line, &column);
 
             StringCchPrintf(buffer, _countof(buffer), _u("%s [%s] (0x%p, Args=%u"), jsBody->GetDisplayName(), jsBody->GetDebugNumberSet(debugStringBuffer), jsFunc,
-                callInfo->Count);
+                callInfo.Count);
             sb.AppendSz(buffer);
 
-            for (uint i = 0; i < callInfo->Count; i++)
+            for (uint i = 0; i < callInfo.Count; i++)
             {
                 StringCchPrintf(buffer, _countof(buffer), _u(", 0x%p"), walker.GetJavascriptArgs()[i]);
                 sb.AppendSz(buffer);

+ 26 - 17
lib/Runtime/Language/JavascriptStackWalker.cpp

@@ -154,7 +154,7 @@ namespace Js
         Assert(IsJavascriptFrame());
         AssertMsg(this->GetCurrentFunction()->IsScriptFunction(), "GetPermanentArguments should not be called for non-script function as there is no slot allocated for it.");
 
-        const uint32 paramCount = GetCallInfo()->Count;
+        const uint32 paramCount = GetCallInfo().Count;
         if (paramCount == 0)
         {
             // glob function doesn't allocate ArgumentsObject slot on stack
@@ -206,8 +206,8 @@ namespace Js
         else
 #endif
         {
-            CallInfo const *callInfo = this->GetCallInfo();
-            if (callInfo->Count == 0)
+            const CallInfo callInfo = this->GetCallInfo();
+            if (callInfo.Count == 0)
             {
                 *pVarThis = JavascriptOperators::OP_GetThis(scriptContext->GetLibrary()->GetUndefined(), moduleId, scriptContext);
                 return false;
@@ -218,14 +218,14 @@ namespace Js
         }
     }
 
-    BOOL IsEval(const CallInfo* callInfo)
+    BOOL IsEval(CallInfo callInfo)
     {
-        return (callInfo->Flags & CallFlags_Eval) != 0;
+        return (callInfo.Flags & CallFlags_Eval) != 0;
     }
 
     BOOL JavascriptStackWalker::IsCallerGlobalFunction() const
     {
-        CallInfo const* callInfo = this->GetCallInfo();
+        const CallInfo callInfo = this->GetCallInfo();
 
         JavascriptFunction* function = this->GetCurrentFunction();
         if (IsLibraryStackFrameEnabled(this->scriptContext) && !function->IsScriptFunction())
@@ -241,14 +241,14 @@ namespace Js
         else
         {
             AssertMsg(FALSE, "Here we should only have script functions which were already parsed/deserialized.");
-            return callInfo->Count == 0 || IsEval(callInfo);
+            return callInfo.Count == 0 || IsEval(callInfo);
         }
     }
 
     BOOL JavascriptStackWalker::IsEvalCaller() const
     {
-        CallInfo const* callInfo = this->GetCallInfo();
-        return (callInfo->Flags & CallFlags_Eval) != 0;
+        const CallInfo callInfo = this->GetCallInfo();
+        return (callInfo.Flags & CallFlags_Eval) != 0;
     }
 
     Var JavascriptStackWalker::GetCurrentNativeArgumentsObject() const
@@ -835,7 +835,7 @@ namespace Js
             if (this->IsJavascriptFrame() && this->GetCurrentFunction() == funcTarget)
             {
                 // Skip internal names
-                Assert( !(this->GetCallInfo()->Flags & CallFlags_InternalFrame) );
+                Assert( !(this->GetCallInfo().Flags & CallFlags_InternalFrame) );
                 return true;
             }
         }
@@ -1012,32 +1012,41 @@ namespace Js
         return GetCurrentFunction(false);
     }
 
-    CallInfo const * JavascriptStackWalker::GetCallInfo(bool includeInlinedFrames /* = true */) const
+    CallInfo JavascriptStackWalker::GetCallInfo(bool includeInlinedFrames /* = true */) const
     {
         Assert(this->IsJavascriptFrame());
+        CallInfo callInfo;
         if (includeInlinedFrames && inlinedFramesBeingWalked)
         {
             // Since we don't support inlining constructors yet, its questionable if we should handle the
             // hidden frame display here?
-            return (CallInfo const *)&inlinedFrameCallInfo;
+            callInfo = inlinedFrameCallInfo;
         }
         else if (this->GetCurrentFunction()->GetFunctionInfo()->IsCoroutine())
         {
             JavascriptGenerator* gen = JavascriptGenerator::FromVar(this->GetCurrentArgv()[JavascriptFunctionArgIndex_This]);
-            return &gen->GetArguments().Info;
+            callInfo = gen->GetArguments().Info;
         }
         else if (this->isNativeLibraryFrame)
         {
             // Return saved callInfo. Do not read from stack as compiler may stackpack/optimize args.
-            return &this->prevNativeLibraryEntry->callInfo;
+            callInfo = this->prevNativeLibraryEntry->callInfo;
         }
         else
         {
-            return (CallInfo const *)&this->GetCurrentArgv()[JavascriptFunctionArgIndex_CallInfo];
+            callInfo = *(CallInfo const *)&this->GetCurrentArgv()[JavascriptFunctionArgIndex_CallInfo];
         }
+
+        if (callInfo.Flags & Js::CallFlags_ExtraArg)
+        {
+            callInfo.Flags = (CallFlags)(callInfo.Flags & ~Js::CallFlags_ExtraArg);
+            callInfo.Count--;
+        }
+
+        return callInfo;
     }
 
-    CallInfo const *JavascriptStackWalker::GetCallInfoFromPhysicalFrame() const
+    CallInfo JavascriptStackWalker::GetCallInfoFromPhysicalFrame() const
     {
         return GetCallInfo(false);
     }
@@ -1080,7 +1089,7 @@ namespace Js
 
     bool JavascriptStackWalker::IsCurrentPhysicalFrameForLoopBody() const
     {
-        return !!(this->GetCallInfoFromPhysicalFrame()->Flags & CallFlags_InternalFrame);
+        return !!(this->GetCallInfoFromPhysicalFrame().Flags & CallFlags_InternalFrame);
     }
 
     bool JavascriptStackWalker::IsWalkable(ScriptContext *scriptContext)

+ 2 - 2
lib/Runtime/Language/JavascriptStackWalker.h

@@ -212,8 +212,8 @@ namespace Js
 
         JavascriptFunction *GetCurrentFunction(bool includeInlinedFrames = true) const;
         void SetCurrentFunction(JavascriptFunction *  function);
-        CallInfo const *GetCallInfo(bool includeInlinedFrames = true) const;
-        CallInfo const *GetCallInfoFromPhysicalFrame() const;
+        CallInfo GetCallInfo(bool includeInlinedFrames = true) const;
+        CallInfo GetCallInfoFromPhysicalFrame() const;
         bool GetThis(Var *pThis, int moduleId) const;
         Js::Var * GetJavascriptArgs() const;
         void **GetCurrentArgv() const;

+ 3 - 2
lib/Runtime/Language/StackTraceArguments.cpp

@@ -68,9 +68,10 @@ namespace Js {
         types = 0;
         if (!walker.IsCallerGlobalFunction())
         {
-            int64 numberOfArguments = walker.GetCallInfo()->Count;
+            const CallInfo callInfo = walker.GetCallInfo();
+            int64 numberOfArguments = callInfo.Count;
             if (numberOfArguments > 0) numberOfArguments --; // Don't consider 'this'
-            if (walker.GetCallInfo()->Flags & Js::CallFlags_ExtraArg)
+            if (callInfo.Flags & Js::CallFlags_ExtraArg)
             {
                 Assert(numberOfArguments > 0 );
                 // skip the last FrameDisplay argument.

+ 3 - 3
lib/Runtime/Library/ArgumentsObject.cpp

@@ -67,9 +67,9 @@ namespace Js
 
         AssertMsg(JavascriptOperators::GetTypeId(funcCaller) == TypeIds_Function, "non function caller");
 
-        CallInfo const *callInfo = walker->GetCallInfo();
-        uint32 paramCount = callInfo->Count;
-        CallFlags flags = callInfo->Flags;
+        const CallInfo callInfo = walker->GetCallInfo();
+        uint32 paramCount = callInfo.Count;
+        CallFlags flags = callInfo.Flags;
 
         if (paramCount == 0 || (flags & CallFlags_Eval))
         {

+ 2 - 2
lib/Runtime/Library/JavascriptFunction.cpp

@@ -2760,9 +2760,9 @@ LABEL1:
                 Var args = nullptr;
                 //Create a copy of the arguments and return it.
 
-                CallInfo const *callInfo = walker.GetCallInfo();
+                const CallInfo callInfo = walker.GetCallInfo();
                 args = JavascriptOperators::LoadHeapArguments(
-                    this, callInfo->Count - 1,
+                    this, callInfo.Count - 1,
                     walker.GetJavascriptArgs(),
                     scriptContext->GetLibrary()->GetNull(),
                     scriptContext->GetLibrary()->GetNull(),