Commit b364bcbe authored by barraclough@apple.com's avatar barraclough@apple.com
Browse files

REGRESSION (r129456): http/tests/security/xss-eval.html is failing on JSC platforms

https://bugs.webkit.org/show_bug.cgi?id=97529

Reviewed by Filip Pizlo.

A recent patch changed JSC's EvalError behaviour; bring this more into line with other browsers.

Source/JavaScriptCore: 

JSC currently throws an EvalError if you try to call eval with a this object that doesn't
match the given eval function. This does not match other browsers, which generally just
ignore the this value that was passed, and eval the string in the eval function's environment.

* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
    - Remove EvalError, ignore passed this value.

LayoutTests: 

* fast/js/eval-cross-window-expected.txt:
* fast/js/eval-cross-window.html:
    - Changed not to expect EvalErrors (this matches other browsers), and modified testThis
      to check that the this object is always set to the global object.
* http/tests/security/resources/xss-eval2.html:
* http/tests/security/resources/xss-eval3.html:
* http/tests/security/xss-eval-expected.txt:
* http/tests/security/xss-eval.html:
    - Updated. Access via the global environment is not a security risk, since the eval is
      accessing it's own document's informantion. Access via the shell attempts to access
      the navigated pages document, tripping an access check & throwing a TypeError.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@129592 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d702a2f9
2012-09-25 Gavin Barraclough <barraclough@apple.com>
REGRESSION (r129456): http/tests/security/xss-eval.html is failing on JSC platforms
https://bugs.webkit.org/show_bug.cgi?id=97529
Reviewed by Filip Pizlo.
A recent patch changed JSC's EvalError behaviour; bring this more into line with other browsers.
* fast/js/eval-cross-window-expected.txt:
* fast/js/eval-cross-window.html:
- Changed not to expect EvalErrors (this matches other browsers), and modified testThis
to check that the this object is always set to the global object.
* http/tests/security/resources/xss-eval2.html:
* http/tests/security/resources/xss-eval3.html:
* http/tests/security/xss-eval-expected.txt:
* http/tests/security/xss-eval.html:
- Updated. Access via the global environment is not a security risk, since the eval is
accessing it's own document's informantion. Access via the shell attempts to access
the navigated pages document, tripping an access check & throwing a TypeError.
2012-09-25 Bear Travis <betravis@adobe.com>
 
[CSS Exclusions] shape-inside line segment layout should be based on line position and height
......@@ -7,34 +7,34 @@ If the test passes, you'll see a series of pass messages below.
PASS: window.eval("x") should be 0 and is.
PASS: frames[0].eval("x") should be 1 and is.
PASS: window.eval("x") should be EvalError and is.
PASS: frames[0].eval("x") should be EvalError and is.
PASS: window.eval("x") should be 1 and is.
PASS: frames[0].eval("x") should be undefined and is.
----- Scope Chain for Getters: -----
PASS: window.eval("xx") should be ReferenceError and is.
PASS: frames[0].eval("xx") should be ReferenceError and is.
PASS: window.eval("xx") should be EvalError and is.
PASS: frames[0].eval("xx") should be EvalError and is.
PASS: window.eval("xx") should be ReferenceError and is.
PASS: frames[0].eval("xx") should be ReferenceError and is.
----- Variable Object: -----
PASS: window.eval("var y; "y" in top") should be true and is.
PASS: frames[0].eval("var y; "y" in top.frames[0]") should be true and is.
PASS: window.eval("var y; "y" in top.frames[0]") should be EvalError and is.
PASS: frames[0].eval("var y; "y" in top") should be EvalError and is.
PASS: window.eval("var y; "y" in top.frames[0]") should be undefined and is.
PASS: frames[0].eval("var y; "y" in top") should be undefined and is.
----- Scope Chain for Setters: -----
PASS: window.eval("z = 1; top.z") should be 1 and is.
PASS: frames[0].eval("z = 2; top.frames[0].z") should be 2 and is.
PASS: window.eval("z = 3; top.frames[0].z") should be EvalError and is.
PASS: frames[0].eval("z = 4; top.z") should be EvalError and is.
PASS: window.eval("z = 3; top.frames[0].z") should be undefined and is.
PASS: frames[0].eval("z = 4; top.z") should be undefined and is.
----- This Object: -----
PASS: window.eval("this") should be [object Window] and is.
PASS: frames[0].eval("this") should be [object Window] and is.
PASS: window.eval("this") should be EvalError and is.
PASS: frames[0].eval("this") should be EvalError and is.
PASS: window.eval("this") should be undefined and is.
PASS: frames[0].eval("this") should be undefined and is.
......@@ -42,11 +42,11 @@ function testGetX()
shouldBe('frames[0].eval("x")', frames[0].eval("x"), 1);
window.eval = frameEval;
shouldBe('window.eval("x")', (function() { try { return window.eval("x") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('window.eval("x")', (function() { try { return window.eval("x") } catch(e) { return e.name; } })(), 1);
window.eval = topEval;
frames[0].eval = topEval;
shouldBe('frames[0].eval("x")', (function() { try { frames[0].eval("x") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('frames[0].eval("x")', (function() { try { frames[0].eval("x") } catch(e) { return e.name; } })(), undefined);
frames[0].eval = frameEval;
}
......@@ -58,11 +58,11 @@ function testGetXX()
shouldBe('frames[0].eval("xx")', (function() { try { return frames[0].eval("xx") } catch(e) { return e.name; } })(), "ReferenceError");
window.eval = frameEval;
shouldBe('window.eval("xx")', (function() { try { return window.eval("xx") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('window.eval("xx")', (function() { try { return window.eval("xx") } catch(e) { return e.name; } })(), "ReferenceError");
window.eval = topEval;
frames[0].eval = topEval;
shouldBe('frames[0].eval("xx")', (function() { try { return frames[0].eval("xx") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('frames[0].eval("xx")', (function() { try { return frames[0].eval("xx") } catch(e) { return e.name; } })(), "ReferenceError");
frames[0].eval = frameEval;
}
......@@ -77,13 +77,13 @@ function testVarY()
delete frames[0].y;
window.eval = frameEval;
shouldBe('window.eval("var y; \"y\" in top.frames[0]")', (function() { try { window.eval("var y; \"y\" in top.frames[0]") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('window.eval("var y; \"y\" in top.frames[0]")', (function() { try { window.eval("var y; \"y\" in top.frames[0]") } catch(e) { return e.name; } })(), undefined);
delete window.y;
delete frames[0].y;
window.eval = topEval;
frames[0].eval = topEval;
shouldBe('frames[0].eval("var y; \"y\" in top")', (function() { try { frames[0].eval("var y; \"y\" in top") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('frames[0].eval("var y; \"y\" in top")', (function() { try { frames[0].eval("var y; \"y\" in top") } catch(e) { return e.name; } })(), undefined);
delete window.y;
delete frames[0].y;
frames[0].eval = frameEval;
......@@ -99,25 +99,25 @@ function testSetZ()
shouldBe('frames[0].eval("z = 2; top.frames[0].z")', frames[0].eval("z = 2; top.frames[0].z"), 2);
window.eval = frameEval;
shouldBe('window.eval("z = 3; top.frames[0].z")', (function() { try { window.eval("z = 3; top.frames[0].z") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('window.eval("z = 3; top.frames[0].z")', (function() { try { window.eval("z = 3; top.frames[0].z") } catch(e) { return e.name; } })(), undefined);
window.eval = topEval;
frames[0].eval = topEval;
shouldBe('frames[0].eval("z = 4; top.z")', (function() { try { frames[0].eval("z = 4; top.z") } catch(e) { return e.name; } })(), "EvalError");
shouldBe('frames[0].eval("z = 4; top.z")', (function() { try { frames[0].eval("z = 4; top.z") } catch(e) { return e.name; } })(), undefined);
frames[0].eval = frameEval;
}
function testThis()
{
shouldBe('window.eval("this")', window.eval("this"), window);
shouldBe('frames[0].eval("this")', frames[0].eval("this"), frames[0]);
shouldBe('window.eval("this")', window.eval.call("wrong", "this"), window);
shouldBe('frames[0].eval("this")', frames[0].eval.call("wrong", "this"), frames[0]);
window.eval = frameEval;
shouldBe('window.eval("this")', (function() { try { window.eval("this"), frames[0] } catch(e) { return e.name; } })(), "EvalError");
shouldBe('window.eval("this")', (function() { try { window.eval.call("wrong", "this"), frames[0] } catch(e) { return e.name; } })(), undefined);
window.eval = topEval;
frames[0].eval = topEval;
shouldBe('frames[0].eval("this")', (function() { try { frames[0].eval("this"), window } catch(e) { return e.name; } })(), "EvalError");
shouldBe('frames[0].eval("this")', (function() { try { frames[0].eval.call("wrong", "this"), window } catch(e) { return e.name; } })(), undefined);
frames[0].eval = frameEval;
}
......
......@@ -85,6 +85,6 @@ PASS: window.moveTo.call(targetWindow, 0, 0); should be 'undefined' and is.
PASS: window.resizeBy.call(targetWindow, 0, 0); should be 'undefined' and is.
PASS: window.resizeTo.call(targetWindow, 0, 0); should be 'undefined' and is.
PASS: window.showModalDialog.call(targetWindow); should be 'undefined' and is.
PASS: window.eval.call(targetWindow, '1+2'); should be 'EvalError: The "this" value passed to eval must be the global object from which eval originated' and is.
PASS: window.eval.call(targetWindow, '1+2'); should be '3' and is.
PASS: window.location.toString.call(targetWindow.location) should be 'undefined' and is.
......@@ -57,7 +57,7 @@ window.onload = function()
shouldBe("window.showModalDialog.call(targetWindow);", "undefined");
// Throws an EvalError and logs to the error console
shouldBe("window.eval.call(targetWindow, '1+2');", '"EvalError: The \\"this\\" value passed to eval must be the global object from which eval originated"');
shouldBe("window.eval.call(targetWindow, '1+2');", '3');
// - Tests for the Location object -
// undefined value indicates failure
......
<script>
document.testExpando = "It's me too!";
parent.childEval = eval;
parent.childEvalCaller = function(s) {
......
<script>
document.testExpando = "It's me three!";
parent.postMessage("done", "*");
</script>
......@@ -4,8 +4,8 @@ This page verifies that you can't use eval to subvert cross-domain checks.
If the test passes, you'll see a pass message below.
PASS: eval.call(frames[0], 'document') should be EvalError and is.
PASS: childEval.call(frames[0], 'document') should be EvalError and is.
PASS: childEvalCaller('document') should be TypeError and is.
PASS: childLocalEvalCaller('document') should be EvalError and is.
PASS: eval.call(frames[0], 'document').testExpando should be It's me! and is.
PASS: childEval.call(frames[0], 'document').testExpando should be It's me too! and is.
PASS: childEvalCaller('document').testExpando should be TypeError and is.
PASS: childLocalEvalCaller('document').testExpando should be It's me too! and is.
......@@ -29,22 +29,25 @@ document.testExpando = "It's me!";
addEventListener("message", function()
{
(function() {
try {
var doc = eval.call(frames[0], 'document');
// V8 execute the eval our scope, which is safe.
shouldBe("documentFromEval", doc.testExpando, "It's me!")
} catch(e) {
// JSC throws an exception, which is also safe.
shouldBe("eval.call(frames[0], 'document')", e.name, "EvalError");
}
})();
shouldBe("childEval.call(frames[0], 'document')", (function() { try { return childEval.call(frames[0], 'document'); } catch(e) { return e.name; } })(), "EvalError");
shouldBe("childEvalCaller('document')", (function() { try { return childEvalCaller('document'); } catch(e) { return e.name; } })(), "TypeError");
shouldBe("childLocalEvalCaller('document')", (function() { try { return childLocalEvalCaller('document'); } catch(e) { return e.name; } })(), "EvalError");
shouldBe("eval.call(frames[0], 'document').testExpando",
(function() { try {
return eval.call(frames[0], 'document').testExpando;
} catch(e) { return e.name; } })(), "It's me!")
shouldBe("childEval.call(frames[0], 'document').testExpando",
(function() { try {
return childEval.call(frames[0], 'document').testExpando;
} catch(e) { return e.name; } })(), "It's me too!");
shouldBe("childEvalCaller('document').testExpando",
(function() { try {
return childEvalCaller('document').testExpando;
} catch(e) { return e.name; } })(), "TypeError");
shouldBe("childLocalEvalCaller('document').testExpando",
(function() { try {
return childLocalEvalCaller('document').testExpando;
} catch(e) { return e.name; } })(), "It's me too!");
if (window.testRunner)
testRunner.notifyDone();
......
2012-09-25 Gavin Barraclough <barraclough@apple.com>
REGRESSION (r129456): http/tests/security/xss-eval.html is failing on JSC platforms
https://bugs.webkit.org/show_bug.cgi?id=97529
Reviewed by Filip Pizlo.
A recent patch changed JSC's EvalError behaviour; bring this more into line with other browsers.
JSC currently throws an EvalError if you try to call eval with a this object that doesn't
match the given eval function. This does not match other browsers, which generally just
ignore the this value that was passed, and eval the string in the eval function's environment.
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
- Remove EvalError, ignore passed this value.
2012-09-25 Filip Pizlo <fpizlo@apple.com>
 
DFG ArrayPush, ArrayPop don't handle clobbering or having a bad time correctly
......
......@@ -497,11 +497,6 @@ static double parseFloat(const String& s)
EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
{
JSObject* thisObject = exec->hostThisValue().toThisObject(exec);
JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject();
if (thisObject != exec->callee()->globalObject()->globalThis())
return throwVMError(exec, createEvalError(exec, ASCIILiteral("The \"this\" value passed to eval must be the global object from which eval originated")));
JSValue x = exec->argument(0);
if (!x.isString())
return JSValue::encode(x);
......@@ -518,12 +513,13 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
return JSValue::encode(parsedObject);
}
JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject();
EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
JSObject* error = eval->compile(exec, calleeGlobalObject);
if (error)
return throwVMError(exec, error);
return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, calleeGlobalObject));
return JSValue::encode(exec->interpreter()->execute(eval, exec, calleeGlobalObject->globalThis(), calleeGlobalObject));
}
EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment