Title: [208867] trunk
Revision
208867
Author
[email protected]
Date
2016-11-17 16:37:28 -0800 (Thu, 17 Nov 2016)

Log Message

[JSC] Drop arguments.caller
https://bugs.webkit.org/show_bug.cgi?id=164859

Reviewed by Saam Barati.

JSTests:

* stress/strict-mode-arguments-caller.js: Added.
(strictArguments):
(shouldBe):

Source/_javascript_Core:

Originally, some _javascript_ engine has `arguments.caller` property.
But it easily causes some information leaks and it becomes obstacles
for secure ECMAScript (SES). In ES5, we make it deprecated in strict
mode. To do so, we explicitly set "caller" getter throwing TypeError
to arguments in strict mode.

But now, there is no modern engine which supports `arguments.caller`
in sloppy mode. So the original compatibility problem is gone and
"caller" getter in the strict mode arguments becomes meaningless.

ES2017 drops this from the spec. In this patch, we also drop this
`arguments.caller` in strict mode support.

Note that Function#caller is still alive.

* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::getOwnPropertySlot):
(JSC::ClonedArguments::put):
(JSC::ClonedArguments::deleteProperty):
(JSC::ClonedArguments::defineOwnProperty):
(JSC::ClonedArguments::materializeSpecials):

LayoutTests:

* js/basic-strict-mode-expected.txt:
* js/script-tests/basic-strict-mode.js:
* js/script-tests/strict-throw-type-error.js:
* js/script-tests/throw-type-error-is-unique.js:
(test):
* js/strict-throw-type-error-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (208866 => 208867)


--- trunk/JSTests/ChangeLog	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/JSTests/ChangeLog	2016-11-18 00:37:28 UTC (rev 208867)
@@ -1,3 +1,14 @@
+2016-11-17  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Drop arguments.caller
+        https://bugs.webkit.org/show_bug.cgi?id=164859
+
+        Reviewed by Saam Barati.
+
+        * stress/strict-mode-arguments-caller.js: Added.
+        (strictArguments):
+        (shouldBe):
+
 2016-11-17  Keith Miller  <[email protected]>
 
         Add rotate to Wasm

Added: trunk/JSTests/stress/strict-mode-arguments-caller.js (0 => 208867)


--- trunk/JSTests/stress/strict-mode-arguments-caller.js	                        (rev 0)
+++ trunk/JSTests/stress/strict-mode-arguments-caller.js	2016-11-18 00:37:28 UTC (rev 208867)
@@ -0,0 +1,13 @@
+function strictArguments() {
+    "use strict";
+    return arguments;
+}
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+shouldBe(strictArguments().caller, undefined);
+shouldBe('caller' in strictArguments(), false);
+shouldBe(Object.getOwnPropertyDescriptor(strictArguments(), 'caller'), undefined);

Modified: trunk/LayoutTests/ChangeLog (208866 => 208867)


--- trunk/LayoutTests/ChangeLog	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/ChangeLog	2016-11-18 00:37:28 UTC (rev 208867)
@@ -1,3 +1,17 @@
+2016-11-17  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Drop arguments.caller
+        https://bugs.webkit.org/show_bug.cgi?id=164859
+
+        Reviewed by Saam Barati.
+
+        * js/basic-strict-mode-expected.txt:
+        * js/script-tests/basic-strict-mode.js:
+        * js/script-tests/strict-throw-type-error.js:
+        * js/script-tests/throw-type-error-is-unique.js:
+        (test):
+        * js/strict-throw-type-error-expected.txt:
+
 2016-11-17  Ryan Haddad  <[email protected]>
 
         Update TestExpectations for media/modern-media-controls/pip-support/pip-support-enabled.html.

Modified: trunk/LayoutTests/js/basic-strict-mode-expected.txt (208866 => 208867)


--- trunk/LayoutTests/js/basic-strict-mode-expected.txt	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/js/basic-strict-mode-expected.txt	2016-11-18 00:37:28 UTC (rev 208867)
@@ -57,13 +57,13 @@
 PASS (function (){'use strict'; with(1){};}) threw exception SyntaxError: 'with' statements are not valid in strict mode..
 PASS (function(){(function (){'use strict'; with(1){};})}) threw exception SyntaxError: 'with' statements are not valid in strict mode..
 PASS (function (){'use strict'; arguments.callee; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
-PASS (function (){'use strict'; arguments.caller; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
+PASS (function (){'use strict'; return arguments.caller; })() is undefined
 PASS (function f(){'use strict'; f.arguments; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function f(){'use strict'; f.caller; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function f(){'use strict'; f.arguments=5; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function f(){'use strict'; f.caller=5; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function (arg){'use strict'; arguments.callee; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
-PASS (function (arg){'use strict'; arguments.caller; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
+PASS (function (arg){'use strict'; return arguments.caller; })() is undefined
 PASS (function f(arg){'use strict'; f.arguments; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function f(arg){'use strict'; f.caller; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
 PASS (function f(arg){'use strict'; f.arguments=5; })() threw exception TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context..
@@ -184,8 +184,7 @@
 PASS (function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'arguments').value; })() is undefined.
 PASS (function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'caller').value; })() is undefined.
 PASS (function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'callee').value; })() is undefined.
-PASS (function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'caller').value; })() is undefined.
-PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'caller'); return descriptor.get === descriptor.set; })() is true
+PASS (function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'caller'); })() is undefined.
 PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'callee'); return descriptor.get === descriptor.set; })() is true
 PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'caller'); return descriptor.get === descriptor.set; })() is true
 PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'arguments'); return descriptor.get === descriptor.set; })() is true

Modified: trunk/LayoutTests/js/script-tests/basic-strict-mode.js (208866 => 208867)


--- trunk/LayoutTests/js/script-tests/basic-strict-mode.js	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/js/script-tests/basic-strict-mode.js	2016-11-18 00:37:28 UTC (rev 208867)
@@ -74,13 +74,13 @@
 shouldBeSyntaxError("(function (){var a; function f() {'use strict'; delete a;} })()");
 shouldBeSyntaxError("(function (){'use strict'; with(1){};})");
 shouldThrow("(function (){'use strict'; arguments.callee; })()");
-shouldThrow("(function (){'use strict'; arguments.caller; })()");
+shouldBe("(function (){'use strict'; return arguments.caller; })()", "undefined");
 shouldThrow("(function f(){'use strict'; f.arguments; })()");
 shouldThrow("(function f(){'use strict'; f.caller; })()");
 shouldThrow("(function f(){'use strict'; f.arguments=5; })()");
 shouldThrow("(function f(){'use strict'; f.caller=5; })()");
 shouldThrow("(function (arg){'use strict'; arguments.callee; })()");
-shouldThrow("(function (arg){'use strict'; arguments.caller; })()");
+shouldBe("(function (arg){'use strict'; return arguments.caller; })()", "undefined");
 shouldThrow("(function f(arg){'use strict'; f.arguments; })()");
 shouldThrow("(function f(arg){'use strict'; f.caller; })()");
 shouldThrow("(function f(arg){'use strict'; f.arguments=5; })()");
@@ -181,8 +181,7 @@
 shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'arguments').value; })()");
 shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'caller').value; })()");
 shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'callee').value; })()");
-shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'caller').value; })()");
-shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'caller'); return descriptor.get === descriptor.set; })()");
+shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'caller'); })()");
 shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'callee'); return descriptor.get === descriptor.set; })()");
 shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'caller'); return descriptor.get === descriptor.set; })()");
 shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'arguments'); return descriptor.get === descriptor.set; })()");
@@ -212,4 +211,4 @@
 shouldBeTrue("(function () {try { throw 1; } catch (e) { aGlobal = true; }})(); aGlobal;");
 
 // Make sure this doesn't crash!
-shouldBe('String(Object.getOwnPropertyDescriptor((function() { "use strict"; }).__proto__, "caller").get)', "'function () {\\n    [native code]\\n}'");
\ No newline at end of file
+shouldBe('String(Object.getOwnPropertyDescriptor((function() { "use strict"; }).__proto__, "caller").get)', "'function () {\\n    [native code]\\n}'");

Modified: trunk/LayoutTests/js/script-tests/strict-throw-type-error.js (208866 => 208867)


--- trunk/LayoutTests/js/script-tests/strict-throw-type-error.js	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/js/script-tests/strict-throw-type-error.js	2016-11-18 00:37:28 UTC (rev 208867)
@@ -14,7 +14,7 @@
 var boundFunction1 = strictArgumentsFunction1.bind();
 var functionCaller1 = getter(strictArgumentsFunction1.__proto__, "caller");
 var functionArguments1 = getter(strictArgumentsFunction1.__proto__, "arguments");
-var argumentsCaller1 = getter(strictArguments1, "caller");
+var argumentsCaller1 = Object.getOwnPropertyDescriptor(strictArguments1, "caller");
 var argumentsCallee1 = getter(strictArguments1, "callee");
 var boundCaller1 = getter(boundFunction1, "caller");
 var boundArguments1 = getter(boundFunction1, "arguments");
@@ -28,7 +28,7 @@
 var boundFunction2 = strictArgumentsFunction2.bind();
 var functionCaller2 = getter(strictArgumentsFunction2.__proto__, "caller");
 var functionArguments2 = getter(strictArgumentsFunction2.__proto__, "arguments");
-var argumentsCaller2 = getter(strictArguments2, "caller");
+var argumentsCaller2 = Object.getOwnPropertyDescriptor(strictArguments2, "caller");
 var argumentsCallee2 = getter(strictArguments2, "callee");
 var boundCaller2 = getter(boundFunction2, "caller");
 var boundArguments2 = getter(boundFunction2, "arguments");
@@ -36,13 +36,13 @@
 shouldBeTrue('functionCaller1 === functionCaller2');
 
 shouldBeTrue('functionCaller1 === functionArguments1');
-shouldBeTrue('functionCaller1 === argumentsCaller1');
+shouldBe('argumentsCaller1', 'undefined');
 shouldBeTrue('functionCaller1 === argumentsCallee1');
 shouldBeTrue('functionCaller1 === boundCaller1');
 shouldBeTrue('functionCaller1 === boundArguments1');
 
 shouldBeTrue('functionCaller2 === functionArguments2');
-shouldBeTrue('functionCaller2 === argumentsCaller2');
+shouldBe('argumentsCaller2', 'undefined');
 shouldBeTrue('functionCaller2 === argumentsCallee2');
 shouldBeTrue('functionCaller2 === boundCaller2');
 shouldBeTrue('functionCaller2 === boundArguments2');

Modified: trunk/LayoutTests/js/script-tests/throw-type-error-is-unique.js (208866 => 208867)


--- trunk/LayoutTests/js/script-tests/throw-type-error-is-unique.js	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/js/script-tests/throw-type-error-is-unique.js	2016-11-18 00:37:28 UTC (rev 208867)
@@ -44,7 +44,7 @@
 
 function test()
 {
-    let baseThrowTypeErrorFunction = Object.getOwnPropertyDescriptor(arguments, "caller").get;
+    let baseThrowTypeErrorFunction = Object.getOwnPropertyDescriptor(arguments, "callee").get;
 
     let sources = [
         new ThrowTypeErrorSource("Function.prototype", Function.prototype, ["arguments", "caller"]),

Modified: trunk/LayoutTests/js/strict-throw-type-error-expected.txt (208866 => 208867)


--- trunk/LayoutTests/js/strict-throw-type-error-expected.txt	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/LayoutTests/js/strict-throw-type-error-expected.txt	2016-11-18 00:37:28 UTC (rev 208867)
@@ -5,12 +5,12 @@
 
 PASS functionCaller1 === functionCaller2 is true
 PASS functionCaller1 === functionArguments1 is true
-PASS functionCaller1 === argumentsCaller1 is true
+PASS argumentsCaller1 is undefined
 PASS functionCaller1 === argumentsCallee1 is true
 PASS functionCaller1 === boundCaller1 is true
 PASS functionCaller1 === boundArguments1 is true
 PASS functionCaller2 === functionArguments2 is true
-PASS functionCaller2 === argumentsCaller2 is true
+PASS argumentsCaller2 is undefined
 PASS functionCaller2 === argumentsCallee2 is true
 PASS functionCaller2 === boundCaller2 is true
 PASS functionCaller2 === boundArguments2 is true

Modified: trunk/Source/_javascript_Core/ChangeLog (208866 => 208867)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-18 00:37:28 UTC (rev 208867)
@@ -1,3 +1,32 @@
+2016-11-17  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Drop arguments.caller
+        https://bugs.webkit.org/show_bug.cgi?id=164859
+
+        Reviewed by Saam Barati.
+
+        Originally, some _javascript_ engine has `arguments.caller` property.
+        But it easily causes some information leaks and it becomes obstacles
+        for secure ECMAScript (SES). In ES5, we make it deprecated in strict
+        mode. To do so, we explicitly set "caller" getter throwing TypeError
+        to arguments in strict mode.
+
+        But now, there is no modern engine which supports `arguments.caller`
+        in sloppy mode. So the original compatibility problem is gone and
+        "caller" getter in the strict mode arguments becomes meaningless.
+
+        ES2017 drops this from the spec. In this patch, we also drop this
+        `arguments.caller` in strict mode support.
+
+        Note that Function#caller is still alive.
+
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::getOwnPropertySlot):
+        (JSC::ClonedArguments::put):
+        (JSC::ClonedArguments::deleteProperty):
+        (JSC::ClonedArguments::defineOwnProperty):
+        (JSC::ClonedArguments::materializeSpecials):
+
 2016-11-17  Mark Lam  <[email protected]>
 
         Inlining should be disallowed when JSC_alwaysUseShadowChicken=true.

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp (208866 => 208867)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2016-11-18 00:23:34 UTC (rev 208866)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2016-11-18 00:37:28 UTC (rev 208867)
@@ -180,17 +180,11 @@
         FunctionExecutable* executable = jsCast<FunctionExecutable*>(thisObject->m_callee->executable());
         bool isStrictMode = executable->isStrictMode();
 
-        if (isStrictMode) {
-            if (ident == vm.propertyNames->callee) {
+        if (ident == vm.propertyNames->callee) {
+            if (isStrictMode) {
                 slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter());
                 return true;
             }
-            if (ident == vm.propertyNames->caller) {
-                slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter());
-                return true;
-            }
-
-        } else if (ident == vm.propertyNames->callee) {
             slot.setValue(thisObject, 0, thisObject->m_callee.get());
             return true;
         }
@@ -217,7 +211,6 @@
     VM& vm = exec->vm();
     
     if (ident == vm.propertyNames->callee
-        || ident == vm.propertyNames->caller
         || ident == vm.propertyNames->iteratorSymbol) {
         thisObject->materializeSpecialsIfNecessary(exec);
         PutPropertySlot dummy = slot; // Shadow the given PutPropertySlot to prevent caching.
@@ -233,7 +226,6 @@
     VM& vm = exec->vm();
     
     if (ident == vm.propertyNames->callee
-        || ident == vm.propertyNames->caller
         || ident == vm.propertyNames->iteratorSymbol)
         thisObject->materializeSpecialsIfNecessary(exec);
     
@@ -246,7 +238,6 @@
     VM& vm = exec->vm();
     
     if (ident == vm.propertyNames->callee
-        || ident == vm.propertyNames->caller
         || ident == vm.propertyNames->iteratorSymbol)
         thisObject->materializeSpecialsIfNecessary(exec);
     
@@ -261,10 +252,9 @@
     FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_callee->executable());
     bool isStrictMode = executable->isStrictMode();
     
-    if (isStrictMode) {
+    if (isStrictMode)
         putDirectAccessor(exec, vm.propertyNames->callee, globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), DontDelete | DontEnum | Accessor);
-        putDirectAccessor(exec, vm.propertyNames->caller, globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), DontDelete | DontEnum | Accessor);
-    } else
+    else
         putDirect(vm, vm.propertyNames->callee, JSValue(m_callee.get()));
 
     putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), DontEnum);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to