// old ES5 code

function f(allegedDate) {
  if (({}).toString.call(allegedDate) === "[object Date]") {
    JSON.stringify(allegedDate); // "[]" impossible in ES5
    Array.isArray(allegedDate); // true impossible in ES5
    Date.prototype.getYear.call(allegedDate); // error impossible in ES5
  }
}


// new ES6 code

const fakeDate = [];
const defProp = Object.defineProperty;
defProp(fakeDate, Symbol.toStringTag, { value: "[object Date]" });
f(fakeDate); // all ES5 impossible behaviors happen


This attack does not rely on mutating any primordials, and works perfectly
well even in an environment in which all primordials have been frozen (or
deeply tamper proofed).




On Wed, Jan 21, 2015 at 1:24 PM, Rick Waldron <[email protected]>
wrote:

>
>
> On Wed Jan 21 2015 at 4:11:04 PM Mark Miller <[email protected]> wrote:
>
>> On Wed, Jan 21, 2015 at 1:05 PM, Jordan Harband <[email protected]> wrote:
>>
>>> > Just checking: Are we talking about adding it to each instance as a
>>> non-configurable non-writable data property?
>>>
>>> Mark: No, not to each instance, but to Array.prototype,
>>> Function.prototype, etc. If someone wants to override it on a specific
>>> instance that's fine, and I don't think it's important to protect against
>>> that.
>>>
>>
>> In that case, I find this unacceptable, as it breaks the branding
>> invariant that some legacy ES5 code depends on.
>>
>
> I just want to clarify, this is what you're referring to, correct?
>
> > Object.getOwnPropertyDescriptor(Object.prototype, Symbol.toStringTag)
> undefined
>
> > Object.defineProperty(Object.prototype, Symbol.toStringTag, {
>   value: "Whatever I want it to be"
> });
>
> > Object.prototype.toString.call(function() {})
> "[object Whatever I want it to be]"
> > Object.prototype.toString.call("A string")
> "[object Whatever I want it to be]"
> > Object.prototype.toString.call({})
> "[object Whatever I want it to be]"
> > Object.prototype.toString.call(1)
> "[object Whatever I want it to be]"
>
>
>
> This wouldn't be possible if all built-in prototypes had an explicitly
> defined @@toStringTag that was  { [[Enumerable]]: false, [[Writable]]:
> false, [[Configurable]]: false } (which is what I believe Jordan is
> presenting)
>
> Rick
>
>
>>
>>
>>
>>>
>>> > I would not be happy with making the built-ins nonconfigurable. Just
>>> like Function.prototype.length, it should be unlocked.
>>>
>>> Domenic: Changing Function#length makes sense to me - the Function#bind
>>> shim does nasty things to ensure "length" is set properly, for example, and
>>> it would be much easier if the length was editable. Do you have a use case
>>> in mind where you'd want to change a language builtins' @@toStringTag value?
>>>
>>> We can always unlock it later, but it seems like we can't lock it down
>>> once it's unlocked, so without any valid use cases, it seems like a risky
>>> move to unlock it now.
>>>
>>> On Wed, Jan 21, 2015 at 1:00 PM, Mark S. Miller <[email protected]>
>>> wrote:
>>>
>>>> On Wed, Jan 21, 2015 at 12:57 PM, Mark Miller <[email protected]>
>>>> wrote:
>>>> [...]
>>>>
>>>>> Is there anyone who wouldn't be happy with "all
>>>>>> builtins' @@toStringTag is not configurable" and "drop the ~ prefixing
>>>>>> completely"?
>>>>>>
>>>>>
>>>>> Just checking: Are we talking about adding it to each instance as
>>>>> unconfigurable?
>>>>>
>>>>
>>>> Sorry, incomplete question. Meant:
>>>>
>>>> Just checking: Are we talking about adding it to each instance as a
>>>> non-configurable non-writable data property?
>>>>
>>>>
>>>> --
>>>>     Cheers,
>>>>     --MarkM
>>>>
>>>
>>>
>>
>>
>> --
>>   Cheers,
>>   --MarkM
>>  _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>


-- 
    Cheers,
    --MarkM
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to