Skip to content

Commit

Permalink
[CVE-2017-11821] Do not pass NewTarget flag on proxy function call tr…
Browse files Browse the repository at this point in the history
…ap if not needed

Currently we always pass the newtarget flag to the function when called through a Proxy's function call trap. This is not necessary if the call is not a constructor call.
  • Loading branch information
aneeshdk authored and agarwal-sandeep committed Oct 10, 2017
1 parent 9a3ad7c commit 2a07ca6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
2 changes: 1 addition & 1 deletion lib/Runtime/Language/InterpreterStackFrame.cpp
Expand Up @@ -1918,7 +1918,7 @@ namespace Js
// generator object. The second argument is the ResumeYieldData which is only needed
// when resuming a generator and so it only used here if a frame already exists on the
// generator object.
AssertMsg(args.Info.Count == 2, "Generator ScriptFunctions should only be invoked by generator APIs with the pair of arguments they pass in -- the generator object and a ResumeYieldData pointer");
AssertOrFailFastMsg(args.Info.Count == 2 && ((args.Info.Flags & CallFlags_ExtraArg) == CallFlags_None), "Generator ScriptFunctions should only be invoked by generator APIs with the pair of arguments they pass in -- the generator object and a ResumeYieldData pointer");
JavascriptGenerator* generator = JavascriptGenerator::FromVar(args[0]);
newInstance = generator->GetFrame();

Expand Down
23 changes: 20 additions & 3 deletions lib/Runtime/Library/JavascriptProxy.cpp
Expand Up @@ -2102,6 +2102,7 @@ namespace Js

BOOL hasOverridingNewTarget = callInfo.Flags & CallFlags_NewTarget;
bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && args[0] != nullptr && RecyclableObject::Is(args[0]);
bool isNewCall = callInfo.Flags & CallFlags_New || callInfo.Flags & CallFlags_NewTarget;

AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
if (!JavascriptProxy::Is(function))
Expand Down Expand Up @@ -2168,7 +2169,16 @@ namespace Js
args.Values[0] = newThisObject;
}

ushort newCount = (ushort)(args.Info.Count + 1);
ushort newCount = (ushort)args.Info.Count;
if (isNewCall)
{
newCount++;
if (!newCount)
{
::Math::DefaultOverflowPolicy();
}
}

Var* newValues;
const unsigned STACK_ARGS_ALLOCA_THRESHOLD = 8; // Number of stack args we allow before using _alloca
Var stackArgs[STACK_ARGS_ALLOCA_THRESHOLD];
Expand All @@ -2181,14 +2191,21 @@ namespace Js
{
newValues = stackArgs;
}
CallInfo calleeInfo((CallFlags)(args.Info.Flags | CallFlags_ExtraArg | CallFlags_NewTarget), newCount);
CallInfo calleeInfo((CallFlags)(args.Info.Flags), newCount);
if (isNewCall)
{
calleeInfo.Flags = (CallFlags)(calleeInfo.Flags | CallFlags_ExtraArg | CallFlags_NewTarget);
}

for (uint argCount = 0; argCount < args.Info.Count; argCount++)
{
newValues[argCount] = args.Values[argCount];
}
#pragma prefast(suppress:6386)
newValues[args.Info.Count] = newTarget;
if (isNewCall)
{
newValues[args.Info.Count] = newTarget;
}

Js::Arguments arguments(calleeInfo, newValues);
Var aReturnValue = JavascriptFunction::CallFunction<true>(targetObj, targetObj->GetEntryPoint(), arguments);
Expand Down

0 comments on commit 2a07ca6

Please sign in to comment.