⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 207997 in webkit


Ignore:
Timestamp:
Oct 27, 2016, 12:41:43 PM (10 years ago)
Author:
mark.lam@apple.com
Message:

Merge r207518. rdar://problem/28216050, rdar://problem/28216232

2016-10-18 Mark Lam <​mark.lam@apple.com>

Invoking Object.prototype.proto accessors directly should throw a TypeError.
​https://bugs.webkit.org/show_bug.cgi?id=154377
<rdar://problem/27330808>

Reviewed by Filip Pizlo and Saam Barati.

JSTests:

  • stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js: Added.

Source/JavaScriptCore:

In a scenario where we cache the proto accessors in global variables, and
later explicitly invoke those accessors as functions, the spec for Function Calls
(see ​https://tc39.github.io/ecma262/#sec-function-calls) states that the function
ref value is of type Reference, and base of ref is an Environment Record. Then,
it follows that the thisValue should be set to refEnv.WithBaseObject()
(see section 4.b.ii of 12.3.4.1 at
​https://tc39.github.io/ecma262/#sec-function-calls-runtime-semantics-evaluation).

refEnv in this case is the environment record that the cached accessors were
found in i.e. the global object. The WithBaseObject() of the global object is
undefined (see details about WithBaseObject at
​https://tc39.github.io/ecma262/#sec-environment-records).

Hence, the proto accessors should see a thisValue of undefined, and throw
TypeErrors. See ​https://tc39.github.io/ecma262/#sec-get-object.prototype.__proto,
​https://tc39.github.io/ecma262/#sec-set-object.prototype.__proto
,
​https://tc39.github.io/ecma262/#sec-toobject, and
​https://tc39.github.io/ecma262/#sec-requireobjectcoercible.

In JSC's implementation, the callee needs to do a ToThis operation on the
incoming "this" argument in order to get the specified thisValue. The
implementations of the proto accessors were not doing this correctly. This
has now been fixed.

  • runtime/JSGlobalObjectFunctions.cpp: (JSC::globalFuncProtoGetter): (JSC::globalFuncProtoSetter):

LayoutTests:

  • http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt:
  • http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt:
  • http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt:
  • http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt:
  • http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html:
  • js/dom/activation-proto-expected.txt:
  • js/dom/script-tests/activation-proto.js:
  • js/object-literal-shorthand-construction-expected.txt:
  • js/script-tests/object-literal-shorthand-construction.js:
  • js/script-tests/sloppy-getter-setter-global-object.js:
  • js/sloppy-getter-setter-global-object-expected.txt:
Location:
branches/safari-602-branch
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-602-branch/JSTests/ChangeLog

    r207916 r207997  
     12016-10-27  Mark Lam  <mark.lam@apple.com>
     2
     3        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
     4
     5    2016-10-18  Mark Lam  <mark.lam@apple.com>
     6
     7            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
     8            https://bugs.webkit.org/show_bug.cgi?id=154377
     9            <rdar://problem/27330808>
     10
     11            Reviewed by Filip Pizlo and Saam Barati.
     12
     13            * stress/object-prototype-proto-accessors-should-throw-on-undefined-this.js: Added.
     14
    1152016-10-24  Matthew Hanson  <matthew_hanson@apple.com>
    216
  • branches/safari-602-branch/LayoutTests/ChangeLog

    r207994 r207997  
     12016-10-27  Mark Lam  <mark.lam@apple.com>
     2
     3        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
     4
     5    2016-10-18  Mark Lam  <mark.lam@apple.com>
     6
     7            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
     8            https://bugs.webkit.org/show_bug.cgi?id=154377
     9            <rdar://problem/27330808>
     10
     11            Reviewed by Filip Pizlo and Saam Barati.
     12
     13            * http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt:
     14            * http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt:
     15            * http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt:
     16            * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt:
     17            * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html:
     18            * js/dom/activation-proto-expected.txt:
     19            * js/dom/script-tests/activation-proto.js:
     20            * js/object-literal-shorthand-construction-expected.txt:
     21            * js/script-tests/object-literal-shorthand-construction.js:
     22            * js/script-tests/sloppy-getter-setter-global-object.js:
     23            * js/sloppy-getter-setter-global-object-expected.txt:
     24
    1252016-10-27  Matthew Hanson  <matthew_hanson@apple.com>
    226
  • branches/safari-602-branch/LayoutTests/fast/dom/Window/script-tests/window-custom-prototype.js

    r202832 r207997  
    11description("Test what happens when you set the window's prototype to various values.");
    22
    3 var originalWindowPrototype = __proto__;
     3var originalWindowPrototype = this.__proto__;
    44var chainPointingBackToWindow = { __proto__: window };
    55var anotherObject = { };
    66
    7 shouldThrow("__proto__ = window; __proto", "'TypeError: cyclic __proto__ value'");
    8 shouldThrow("__proto__ = chainPointingBackToWindow; __proto__", "'TypeError: cyclic __proto__ value'");
    9 shouldBe("__proto__ = 1; __proto__", "originalWindowPrototype");
    10 shouldBe("__proto__ = 'a string'; __proto__", "originalWindowPrototype");
    11 shouldBe("__proto__ = anotherObject; __proto__", "anotherObject");
    12 shouldThrow("anotherObject.__proto__ = window; __proto__", "'TypeError: cyclic __proto__ value'");
    13 shouldBe("__proto__ = 1; __proto__", "anotherObject");
    14 shouldBe("__proto__ = 'a string'; __proto__", "anotherObject");
    15 shouldBe("__proto__ = anotherObject; __proto__", "anotherObject");
    16 shouldBe("__proto__ = originalWindowPrototype; __proto__", "originalWindowPrototype");
     7shouldThrow("this.__proto__ = window; this.__proto__", "'TypeError: cyclic __proto__ value'");
     8shouldThrow("this.__proto__ = chainPointingBackToWindow; this.__proto__", "'TypeError: cyclic __proto__ value'");
     9shouldBe("this.__proto__ = 1; this.__proto__", "originalWindowPrototype");
     10shouldBe("this.__proto__ = 'a string'; this.__proto__", "originalWindowPrototype");
     11shouldBe("this.__proto__ = anotherObject; this.__proto__", "anotherObject");
     12shouldThrow("anotherObject.__proto__ = window; this.__proto__", "'TypeError: cyclic __proto__ value'");
     13shouldBe("this.__proto__ = 1; this.__proto__", "anotherObject");
     14shouldBe("this.__proto__ = 'a string'; this.__proto__", "anotherObject");
     15shouldBe("this.__proto__ = anotherObject; this.__proto__", "anotherObject");
     16shouldBe("this.__proto__ = originalWindowPrototype; this.__proto__", "originalWindowPrototype");
    1717shouldBe("anotherObject.__proto__ = window; anotherObject.__proto__", "window");
    18 shouldBe("__proto__ = null; __proto__", "null");
     18shouldBe("this.__proto__ = null; this.__proto__", "undefined");
  • branches/safari-602-branch/LayoutTests/fast/dom/Window/window-custom-prototype-expected.txt

    r202832 r207997  
    44
    55
    6 PASS __proto__ = window; __proto threw exception TypeError: cyclic __proto__ value.
    7 PASS __proto__ = chainPointingBackToWindow; __proto__ threw exception TypeError: cyclic __proto__ value.
    8 PASS __proto__ = 1; __proto__ is originalWindowPrototype
    9 PASS __proto__ = 'a string'; __proto__ is originalWindowPrototype
    10 PASS __proto__ = anotherObject; __proto__ is anotherObject
    11 PASS anotherObject.__proto__ = window; __proto__ threw exception TypeError: cyclic __proto__ value.
    12 PASS __proto__ = 1; __proto__ is anotherObject
    13 PASS __proto__ = 'a string'; __proto__ is anotherObject
    14 PASS __proto__ = anotherObject; __proto__ is anotherObject
    15 PASS __proto__ = originalWindowPrototype; __proto__ is originalWindowPrototype
     6PASS this.__proto__ = window; this.__proto__ threw exception TypeError: cyclic __proto__ value.
     7PASS this.__proto__ = chainPointingBackToWindow; this.__proto__ threw exception TypeError: cyclic __proto__ value.
     8PASS this.__proto__ = 1; this.__proto__ is originalWindowPrototype
     9PASS this.__proto__ = 'a string'; this.__proto__ is originalWindowPrototype
     10PASS this.__proto__ = anotherObject; this.__proto__ is anotherObject
     11PASS anotherObject.__proto__ = window; this.__proto__ threw exception TypeError: cyclic __proto__ value.
     12PASS this.__proto__ = 1; this.__proto__ is anotherObject
     13PASS this.__proto__ = 'a string'; this.__proto__ is anotherObject
     14PASS this.__proto__ = anotherObject; this.__proto__ is anotherObject
     15PASS this.__proto__ = originalWindowPrototype; this.__proto__ is originalWindowPrototype
    1616PASS anotherObject.__proto__ = window; anotherObject.__proto__ is window
    17 PASS __proto__ = null; __proto__ is null
     17PASS this.__proto__ = null; this.__proto__ is undefined
    1818PASS successfullyParsed is true
    1919
  • branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html

    r120174 r207997  
    1616
    1717window.onload = function() {
    18   __proto__ = targetWindow;
     18  this.__proto__ = targetWindow;
    1919  shouldBeUndefined('targetWindow.myinput');
    2020}
  • branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto.html

    r120174 r207997  
    3131  originalSetTimeout = setTimeout;
    3232
    33   __proto__ = targetWindow;
     33  this.__proto__ = targetWindow;
    3434
    3535  var needsCheck = false;
  • branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html

    r120174 r207997  
    1717  originalLocation = location;
    1818
    19   __proto__ = targetWindow;
     19  this.__proto__ = targetWindow;
    2020
    2121  shouldBeTrue('location === originalLocation');
  • branches/safari-602-branch/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html

    r120174 r207997  
    1717  originalInnerHeight = innerHeight;
    1818
    19   __proto__ = targetWindow;
     19  this.__proto__ = targetWindow;
    2020
    2121  shouldBeTrue('innerHeight === originalInnerHeight');
  • branches/safari-602-branch/LayoutTests/js/dom/activation-proto-expected.txt

    r156066 r207997  
    44
    55
    6 PASS (function() { __proto__.testVariable = 'found'; return window.testVariable; })() is 'found'
     6PASS (function() { this.__proto__.testVariable = 'found'; return window.testVariable; })() is 'found'
    77PASS successfullyParsed is true
    88
  • branches/safari-602-branch/LayoutTests/js/dom/script-tests/activation-proto.js

    r156066 r207997  
    55);
    66
    7 shouldBe("(function() { __proto__.testVariable = 'found'; return window.testVariable; })()", "'found'");
     7shouldBe("(function() { this.__proto__.testVariable = 'found'; return window.testVariable; })()", "'found'");
  • branches/safari-602-branch/LayoutTests/js/object-literal-shorthand-construction-expected.txt

    r181179 r207997  
    6262PASS !!Object.getOwnPropertyDescriptor({set 'x'(value){}}, 'x').set is true
    6363PASS !!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set is true
    64 PASS __proto__ = []; ({__proto__: __proto__}) instanceof Array is true
    65 PASS __proto__ = []; ({__proto__}) instanceof Array is false
    66 PASS __proto__ = []; ({__proto__}).__proto__ instanceof Array is true
     64PASS this.__proto__ = []; ({__proto__: __proto__}) instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
     65PASS this.__proto__ = []; ({__proto__}) instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
     66PASS this.__proto__ = []; ({__proto__}).__proto__ instanceof Array threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
    6767PASS successfullyParsed is true
    6868
  • branches/safari-602-branch/LayoutTests/js/script-tests/object-literal-shorthand-construction.js

    r181179 r207997  
    111111
    112112// __proto__ shorthand should be not modify the prototype.
    113 shouldBeTrue("__proto__ = []; ({__proto__: __proto__}) instanceof Array");
    114 shouldBeFalse("__proto__ = []; ({__proto__}) instanceof Array");
    115 shouldBeTrue("__proto__ = []; ({__proto__}).__proto__ instanceof Array");
     113shouldThrow("this.__proto__ = []; ({__proto__: __proto__}) instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');
     114shouldThrow("this.__proto__ = []; ({__proto__}) instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');
     115shouldThrow("this.__proto__ = []; ({__proto__}).__proto__ instanceof Array", '"TypeError: Object.prototype.__proto__ called on null or undefined"');
  • branches/safari-602-branch/LayoutTests/js/script-tests/sloppy-getter-setter-global-object.js

    r183275 r207997  
    2626shouldNotThrow("Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set(['foo'])");
    2727
    28 shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)()", "\"TypeError: Can't convert undefined or null to object\"");
    29 shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo'])", "\"TypeError: Can't convert undefined or null to object\"");
     28shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)()", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
     29shouldThrow("(0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo'])", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
    3030
    3131
    3232var top_level_sloppy_getter = Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get;
    33 shouldNotThrow("top_level_sloppy_getter();");
     33shouldThrow("top_level_sloppy_getter();", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
    3434
    3535var top_level_sloppy_setter = Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set;
    36 shouldNotThrow("top_level_sloppy_setter(['foo']);");
     36shouldThrow("top_level_sloppy_setter(['foo']);", "\"TypeError: Object.prototype.__proto__ called on null or undefined\"");
  • branches/safari-602-branch/LayoutTests/js/sloppy-getter-setter-global-object-expected.txt

    r183275 r207997  
    99PASS Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get() did not throw exception.
    1010PASS Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set(['foo']) did not throw exception.
    11 PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)() threw exception TypeError: Can't convert undefined or null to object.
    12 PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo']) threw exception TypeError: Can't convert undefined or null to object.
    13 PASS top_level_sloppy_getter(); did not throw exception.
    14 PASS top_level_sloppy_setter(['foo']); did not throw exception.
     11PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').get)() threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
     12PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo']) threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
     13PASS top_level_sloppy_getter(); threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
     14PASS top_level_sloppy_setter(['foo']); threw exception TypeError: Object.prototype.__proto__ called on null or undefined.
    1515PASS successfullyParsed is true
    1616
  • branches/safari-602-branch/Source/JavaScriptCore/ChangeLog

    r207945 r207997  
     12016-10-27  Mark Lam  <mark.lam@apple.com>
     2
     3        Merge r207518. rdar://problem/28216050, rdar://problem/28216232
     4
     5    2016-10-18  Mark Lam  <mark.lam@apple.com>
     6
     7            Invoking Object.prototype.__proto__ accessors directly should throw a TypeError.
     8            https://bugs.webkit.org/show_bug.cgi?id=154377
     9            <rdar://problem/27330808>
     10
     11            Reviewed by Filip Pizlo and Saam Barati.
     12
     13            In a scenario where we cache the __proto__ accessors in global variables, and
     14            later explicitly invoke those accessors as functions, the spec for Function Calls
     15            (see https://tc39.github.io/ecma262/#sec-function-calls) states that the function
     16            ref value is of type Reference, and base of ref is an Environment Record.  Then,
     17            it follows that the thisValue should be set to refEnv.WithBaseObject()
     18            (see section 4.b.ii of 12.3.4.1 at
     19            https://tc39.github.io/ecma262/#sec-function-calls-runtime-semantics-evaluation).
     20
     21            refEnv in this case is the environment record that the cached accessors were
     22            found in i.e. the global object.  The WithBaseObject() of the global object is
     23            undefined (see details about WithBaseObject at
     24            https://tc39.github.io/ecma262/#sec-environment-records).
     25
     26            Hence, the __proto__ accessors should see a thisValue of undefined, and throw
     27            TypeErrors.  See https://tc39.github.io/ecma262/#sec-get-object.prototype.__proto__,
     28            https://tc39.github.io/ecma262/#sec-set-object.prototype.__proto__,
     29            https://tc39.github.io/ecma262/#sec-toobject, and
     30            https://tc39.github.io/ecma262/#sec-requireobjectcoercible.
     31
     32            In JSC's implementation, the callee needs to do a ToThis operation on the
     33            incoming "this" argument in order to get the specified thisValue.  The
     34            implementations of the __proto__ accessors were not doing this correctly.  This
     35            has now been fixed.
     36
     37            * runtime/JSGlobalObjectFunctions.cpp:
     38            (JSC::globalFuncProtoGetter):
     39            (JSC::globalFuncProtoSetter):
     40
    1412016-10-24  Matthew Hanson  <matthew_hanson@apple.com>
    242
  • branches/safari-602-branch/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r202890 r207997  
    5353
    5454namespace JSC {
     55
     56static const char* const ObjectProtoCalledOnNullOrUndefinedError = "Object.prototype.__proto__ called on null or undefined";
    5557
    5658template<typename CallbackWhenNoException>
    … …  
    888890EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
    889891{
    890     if (exec->thisValue().isUndefinedOrNull())
    891         return throwVMTypeError(exec, ASCIILiteral("Can't convert undefined or null to object"));
    892 
    893     JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
    894 
     892    JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
     893    if (thisValue.isUndefinedOrNull())
     894        return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
     895
     896    JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue);
    895897    if (!thisObject) {
    896898        JSObject* prototype = exec->thisValue().synthesizePrototype(exec);
    … …  
    945947EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
    946948{
    947     if (exec->thisValue().isUndefinedOrNull())
    948         return throwVMTypeError(exec, ASCIILiteral("Can't convert undefined or null to object"));
     949    JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
     950    if (thisValue.isUndefinedOrNull())
     951        return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError));
    949952
    950953    JSValue value = exec->argument(0);
    951954
    952     JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
     955    JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue);
    953956
    954957    // Setting __proto__ of a primitive should have no effect.
Note: See TracChangeset for help on using the changeset viewer.