@@toStringTag spoofing for null and undefined

classic Classic list List threaded Threaded
125 messages Options
1234 ... 7
Reply | Threaded
Open this post in threaded view
|

@@toStringTag spoofing for null and undefined

Nicholas C. Zakas-3
According to 19.1.3.6 Object.prototype.toString() [1], it's possible to
do this:

```js
function Foo(){}

Foo.prototype[Symbol.toStringTag] = "Null";

Object.prototype.toString.call(new Foo());   // "[object Null]"
```

It seems like `"Null"` and `"Undefined"` should be added to the step
17(b) list of exceptions to prevent spoofing of null and undefined
values using this approach.

I couldn't think of a reason why the current behavior would make sense,
but if I'm off base, feel free to correct me. :)

[1]:
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring

--
___________________________
Nicholas C. Zakas
http://www.nczonline.net

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: @@toStringTag spoofing for null and undefined

Domenic Denicola
I think we should remove those anti-spoofing "protections". I anticipate a discussion at TC39 next week.

-----Original Message-----
From: es-discuss [mailto:[hidden email]] On Behalf Of Nicholas C. Zakas
Sent: Monday, January 19, 2015 17:59
To: es-discuss
Subject: @@toStringTag spoofing for null and undefined

According to 19.1.3.6 Object.prototype.toString() [1], it's possible to do this:

```js
function Foo(){}

Foo.prototype[Symbol.toStringTag] = "Null";

Object.prototype.toString.call(new Foo());   // "[object Null]"
```

It seems like `"Null"` and `"Undefined"` should be added to the step
17(b) list of exceptions to prevent spoofing of null and undefined values using this approach.

I couldn't think of a reason why the current behavior would make sense, but if I'm off base, feel free to correct me. :)

[1]:
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring

--
___________________________
Nicholas C. Zakas
http://www.nczonline.net

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
Can we get a leg up, rather than wait for a f2f? This thread seems fine
for further discussion and simplifying proposals.

/be

Domenic Denicola wrote:
> I think we should remove those anti-spoofing "protections". I anticipate a discussion at TC39 next week.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Allen Wirfs-Brock
In reply to this post by Nicholas C. Zakas-3

On Jan 19, 2015, at 2:59 PM, Nicholas C. Zakas wrote:

According to 19.1.3.6 Object.prototype.toString() [1], it's possible to do this:

```js
function Foo(){}

Foo.prototype[Symbol.toStringTag] = "Null";

Object.prototype.toString.call(new Foo());   // "[object Null]"
```

It seems like `"Null"` and `"Undefined"` should be added to the step 17(b) list of exceptions to prevent spoofing of null and undefined values using this approach.

I couldn't think of a reason why the current behavior would make sense, but if I'm off base, feel free to correct me. :)

[1]: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring


Let's be clear, the legacy usage we are trying to preserve is specifically detecting whether an object is one of those than in ES5 would of had a [[Class]] value that was one of "Function", "Array", "RegExp", "Date", "Arguments", "Error", "String", "Number",  "Boolean".

In ES<=5, O.p.toString just reported, an object's [[Class]] value and no object created using a JS level constructor could have those specific [[Class]] values.  So O.P.toString worked as a brand check for those specific built-in object representations.

We can't know everything JS programmers might have used that brand check for, so we need to preserve that O.p.toString behavior for those specific built-ins.  Part of the behavior we want to preserve is that only the implementation provided built-ins could eturn those specific values via O.p.toString (this was a requirement  introduced by ES5).   The spoofing protection is design to preserve that requirement.

"null" and "undefined" were never [[Class]] values.  And where actually introduced into O.p.toString by ES5.1 to fix a specific problem that was discovered after ES5 was completed(see threads starting at https://mail.mozilla.org/pipermail/es5-discuss/2010-June/003581.html and https://mail.mozilla.org/pipermail/es5-discuss/2010-June/003585.html ). 

I find it a stretch to believe that anyone is depending upon using O.p.toString as a non-spoofable brand check for null or undefined.

Allen 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: @@toStringTag spoofing for null and undefined

Domenic Denicola
In reply to this post by Brendan Eich-2
From: Brendan Eich [mailto:[hidden email]]

> Can we get a leg up, rather than wait for a f2f? This thread seems fine for further discussion and simplifying proposals.

Well, to be clear, I'd prefer we not change anything at all. It's too late to be tweaking something that's been set in the spec for a very long time now.

But it appears that we have some relitigation on this particular topic [on the agenda anyway][1]:

>  @@toStringTag (rationales) (Jordan Harband)
>
> - Missing unspoofable builtin values (Math, JSON, Object): spec bug
> - Should built-in @@toStringTag values have { configurable: false }?
> - Should Object.prototype.toString add a prefix to all non-built-in @@toStringTag values?

It seems the "protections" in the spec so far have given some the misleading impression that we want to encourage O.p.toString as an unspoofable [[Class]] test. (Not that [[Class]] even exists anymore!) But as Allen points out, that's not the idea at all. And I'm loathe to perpetuate that usage of them---or even the impression that they should be used that way. (Nominal-typing bad! Especially in ES6/ES7/etc. where proxies/value types/etc. give us the ability to perfectly emulate the characteristics of those types!)

So if we're going to have some kind of debate about @@toStringTag anyway, I plan to be representing the side that thinks we shouldn't be protecting anything, and should just dumb it down to a simple double-dispatch protocol.

[1]: https://github.com/tc39/agendas/blob/master/2015/01.md
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: @@toStringTag spoofing for null and undefined

Gary Guo
Agree with Allen. As long as we can prevent spoofing for string, number, etc (ES5 defined), we should leave others as is, otherwise people may argue that Map, WeakMap, etc should be unspoofable as well.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
In reply to this post by Domenic Denicola
Domenic Denicola wrote:
> From: Brendan Eich [mailto:[hidden email]]
>
>> >  Can we get a leg up, rather than wait for a f2f? This thread seems fine for further discussion and simplifying proposals.
>
> Well, to be clear, I'd prefer we not change anything at all. It's too late to be tweaking something that's been set in the spec for a very long time now.
>
> But it appears that we have some relitigation on this particular topic [on the agenda anyway][1]:

Toxic terms like "relitigation", heard it from from RealAlexRussell and
it sucked then too, are out of line -- we are not lawyers. Also, new
TC39 rep Jordan Harband of Twitter raised this at the last meeting,
asked Allen about working on it, got a green light.

>> >    @@toStringTag (rationales) (Jordan Harband)
>> >
>> >  - Missing unspoofable builtin values (Math, JSON, Object): spec bug
>> >  - Should built-in @@toStringTag values have { configurable: false }?
>> >  - Should Object.prototype.toString add a prefix to all non-built-in @@toStringTag values?
>
> It seems the "protections" in the spec so far have given some the misleading impression that we want to encourage O.p.toString as an unspoofable [[Class]] test. (Not that [[Class]] even exists anymore!) But as Allen points out, that's not the idea at all. And I'm loathe to perpetuate that usage of them---or even the impression that they should be used that way. (Nominal-typing bad!

That "X-typing bad!" line is not helpful. (What is this, a sports/beer
commercial?)

Even structural typing fans such as Mark Miller have noted in their
research results the benefits of nominal types for certain use-cases.
Sometimes you need to know your implementation. This is the exception to
the rule, but it's not always and everywhere "bad!".

>   Especially in ES6/ES7/etc. where proxies/value types/etc. give us the ability to perfectly emulate the characteristics of those types!)

Yes, we want to complete the MOP so nominal types are equivalent to
branded structural types, a la Modula 3, and per David Ungar's position
articulated many times over the years (I heard David say it to Tom Van
Cutsem in person at SPLASH 2011, re: Proxies not interceding fully for
all types). But we aren't there yet.

Anyway, this has little to do with getting the details of toStringTag in
the best shape we can for ES6. Perhaps Jordan will weigh in, but in any
case, I found his links and questions from the agenda helpful -- others
may too. Here they are:

1.
https://github.com/ljharb/agendas/wiki/January-TC39-@@toStringTag-discussion

2. https://bugs.ecmascript.org/show_bug.cgi?id=3506

3. Should built-in `@@toStringTag` values have `{ configurable: false }`?

4. Should `Object.prototype.toString` add a prefix to *all* non-built-in
`@@toStringTag` values?

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Mark S. Miller-2


On Tue, Jan 20, 2015 at 10:05 AM, Brendan Eich <[hidden email]> wrote:
Domenic Denicola wrote:
From: Brendan Eich [mailto:[hidden email]]

>  Can we get a leg up, rather than wait for a f2f? This thread seems fine for further discussion and simplifying proposals.

Well, to be clear, I'd prefer we not change anything at all. It's too late to be tweaking something that's been set in the spec for a very long time now.

But it appears that we have some relitigation on this particular topic [on the agenda anyway][1]:

Toxic terms like "relitigation", heard it from from RealAlexRussell and it sucked then too, are out of line -- we are not lawyers. Also, new TC39 rep Jordan Harband of Twitter raised this at the last meeting, asked Allen about working on it, got a green light.

>    @@toStringTag (rationales) (Jordan Harband)
>
>  - Missing unspoofable builtin values (Math, JSON, Object): spec bug
>  - Should built-in @@toStringTag values have { configurable: false }?
>  - Should Object.prototype.toString add a prefix to all non-built-in @@toStringTag values?

It seems the "protections" in the spec so far have given some the misleading impression that we want to encourage O.p.toString as an unspoofable [[Class]] test. (Not that [[Class]] even exists anymore!) But as Allen points out, that's not the idea at all. And I'm loathe to perpetuate that usage of them---or even the impression that they should be used that way. (Nominal-typing bad!

That "X-typing bad!" line is not helpful. (What is this, a sports/beer commercial?)

Even structural typing fans such as Mark Miller have noted in their research results the benefits of nominal types for certain use-cases. Sometimes you need to know your implementation. This is the exception to the rule, but it's not always and everywhere "bad!".

Yes, but I would put it more positively. Nominal and Structural typing are about different things. Neither subsume the other. Nominal types are often misunderstood to be about the string-name of types or some equally non-generative notion of type, so I prefer to use the brand terminology. The classic Types are Not Sets <http://dl.acm.org/citation.cfm?doid=512927.512938>, IIRC, uses the term "trademarking" instead with the same meaning. If anyone has a link to the actual pdf, please post.


 


  Especially in ES6/ES7/etc. where proxies/value types/etc. give us the ability to perfectly emulate the characteristics of those types!)

Yes, we want to complete the MOP so nominal types are equivalent to branded structural types, a la Modula 3, and per David Ungar's position articulated many times over the years (I heard David say it to Tom Van Cutsem in person at SPLASH 2011, re: Proxies not interceding fully for all types). But we aren't there yet.

I don't understand this paragraph. Are you saying that you want a proxy to be able to intercept and emulate the brand check, while somehow preserving the integrity implied by the brand check?
 

Anyway, this has little to do with getting the details of toStringTag in the best shape we can for ES6. Perhaps Jordan will weigh in, but in any case, I found his links and questions from the agenda helpful -- others may too. Here they are:

1. https://github.com/ljharb/agendas/wiki/January-TC39-@@toStringTag-discussion

2. https://bugs.ecmascript.org/show_bug.cgi?id=3506

3. Should built-in `@@toStringTag` values have `{ configurable: false }`?

4. Should `Object.prototype.toString` add a prefix to *all* non-built-in `@@toStringTag` values?

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Jordan Harband
"X is bad" is, quite frankly, mostly irrelevant here. When X is bad in JS, then TC39 seems to have gone with primarily one of two choices: use strict mode to remove it, or, provide a better option Y so that developers *want* to move away from X and start using Y. In this case, the value of type checking doesn't matter - people do it, and so it must be considered.

There are two primary usages of Object.prototype.toString in my eyes:
 - constructs like `Object.prototype.toString.call(new String('foo')) === Object.prototype.toString.call('foo')` (or using that to throw an explicit error "don't use object forms of primitives") which ensures that people using my code won't fall into the very common footgun (thanks, Java) of using boxed primitives. (The same issue will apply to Symbols in ES6, but at least I can do `typeof Symbol.prototype.toString.call(value) === 'symbol'`)
 - Testing of values from other realms (namely iframes). `Object.prototype.toString.call(value) === '[object Array]'` is a remarkably consistently written return value of an `Array.isArray` polyfill, since it works no matter how somebody has monkeyed with any global Array object.

Certainly it is trivial to construct a malicious array, for example, and pass that around breaking all sorts of things. The goal, in my opinion, of Object.prototype.toString checking is *not* security - it's avoiding common developer hazards. In other words, I want my code to fail fast when the developer unintentionally passes me the wrong thing - something that I think we can agree happens often.

1) configurability of @@toStringTag
It appears that TC39 considers it important to not break existing JS code with spec changes. Thus, `Object.prototype.toString.call(foo)`, for any ES5 value "foo", must always and forever return the same value that it returned in ES5 - otherwise, existing code may follow different code paths in ES5 versus ES6, which is a hazard. This leads me to the belief that @@toStringTag values on ES5 builtins should never be changeable.

Some have replied to this, "if you don't run first, all bets are off - freeze it if you want it". Fair point! If you don't run first and keep a reference to Object.prototype.toString, you're screwed anyways. However, in ES5, if I *do* run first, I have 100% opt-in protection against somebody breaking things I care about. Essentially all polyfilled `Array.isArray` code on the web could break if it is possible to redefine `Array.prototype[@@toStringTag]` (in any realm, not just the one I start in), which is currently possible by default in ES6.

I believe that all built-in objects, in all realms, should have a nonconfigurable @@toStringTag for this reason.

2) Since people *are* doing this type checking, if I make an object that defines its @@toStringTag value to return "Array", I will break code that does this. (Hence the protections in https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) I've filed https://bugs.ecmascript.org/show_bug.cgi?id=3506 to discuss the missing values (namely Math, JSON, and Object, and Null, and Undefined have been mentioned as well).

Currently, the spec handles this by including a whitelist of values, and specifying that any value not in this list receives a "~" prefix. (The value of the prefix itself is irrelevant, let's please not bikeshed it).

My proposal is that rather than maintain a whitelist, and have that added complexity, that ES6 specifies that any user-defined @@toStringTag value will *always* and unconditionally have a prefix applied.

--------------------


I believe that either of these proposals by themselves will be a win - but with both together, "nominal type checking" / branding code will continue to work, and there will be no hazards or footguns by default.

For those who dislike this kind of code, I challenge you and the committee to finalize and publish a better approach for answering the question "does this behave like an array" or "does this behave like a map" that work cross-realm (besides exhaustive duck-typing and/or feature detection), rather than attempting to simply oppress what many consider to be a valid approach, and a functional and existing one.

This is my first post to the list, so please be gentle :-) I will take any feedback provided!

On Tue, Jan 20, 2015 at 11:26 AM, Mark S. Miller <[hidden email]> wrote:


On Tue, Jan 20, 2015 at 10:05 AM, Brendan Eich <[hidden email]> wrote:
Domenic Denicola wrote:
From: Brendan Eich [mailto:[hidden email]]

>  Can we get a leg up, rather than wait for a f2f? This thread seems fine for further discussion and simplifying proposals.

Well, to be clear, I'd prefer we not change anything at all. It's too late to be tweaking something that's been set in the spec for a very long time now.

But it appears that we have some relitigation on this particular topic [on the agenda anyway][1]:

Toxic terms like "relitigation", heard it from from RealAlexRussell and it sucked then too, are out of line -- we are not lawyers. Also, new TC39 rep Jordan Harband of Twitter raised this at the last meeting, asked Allen about working on it, got a green light.

>    @@toStringTag (rationales) (Jordan Harband)
>
>  - Missing unspoofable builtin values (Math, JSON, Object): spec bug
>  - Should built-in @@toStringTag values have { configurable: false }?
>  - Should Object.prototype.toString add a prefix to all non-built-in @@toStringTag values?

It seems the "protections" in the spec so far have given some the misleading impression that we want to encourage O.p.toString as an unspoofable [[Class]] test. (Not that [[Class]] even exists anymore!) But as Allen points out, that's not the idea at all. And I'm loathe to perpetuate that usage of them---or even the impression that they should be used that way. (Nominal-typing bad!

That "X-typing bad!" line is not helpful. (What is this, a sports/beer commercial?)

Even structural typing fans such as Mark Miller have noted in their research results the benefits of nominal types for certain use-cases. Sometimes you need to know your implementation. This is the exception to the rule, but it's not always and everywhere "bad!".

Yes, but I would put it more positively. Nominal and Structural typing are about different things. Neither subsume the other. Nominal types are often misunderstood to be about the string-name of types or some equally non-generative notion of type, so I prefer to use the brand terminology. The classic Types are Not Sets <http://dl.acm.org/citation.cfm?doid=512927.512938>, IIRC, uses the term "trademarking" instead with the same meaning. If anyone has a link to the actual pdf, please post.


 


  Especially in ES6/ES7/etc. where proxies/value types/etc. give us the ability to perfectly emulate the characteristics of those types!)

Yes, we want to complete the MOP so nominal types are equivalent to branded structural types, a la Modula 3, and per David Ungar's position articulated many times over the years (I heard David say it to Tom Van Cutsem in person at SPLASH 2011, re: Proxies not interceding fully for all types). But we aren't there yet.

I don't understand this paragraph. Are you saying that you want a proxy to be able to intercept and emulate the brand check, while somehow preserving the integrity implied by the brand check?
 

Anyway, this has little to do with getting the details of toStringTag in the best shape we can for ES6. Perhaps Jordan will weigh in, but in any case, I found his links and questions from the agenda helpful -- others may too. Here they are:

1. https://github.com/ljharb/agendas/wiki/January-TC39-@@toStringTag-discussion

2. https://bugs.ecmascript.org/show_bug.cgi?id=3506

3. Should built-in `@@toStringTag` values have `{ configurable: false }`?

4. Should `Object.prototype.toString` add a prefix to *all* non-built-in `@@toStringTag` values?

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: @@toStringTag spoofing for null and undefined

Domenic Denicola
From: es-discuss [mailto:[hidden email]] On Behalf Of Jordan Harband

> It appears that TC39 considers it important to not break existing JS code with spec changes. Thus, `Object.prototype.toString.call(foo)`, for any ES5 value "foo", must always and forever return the same value that it returned in ES5 - otherwise, existing code may follow different code paths in ES5 versus ES6, which is a hazard. This leads me to the belief that @@toStringTag values on ES5 builtins should never be changeable.

I don't think this reasoning, or in fact the reasoning that leads to the current tilde-prefixing, is sound.

First we must realize that if we were to remove the tilde-prefixing, no deployed code would ever break. Only new code (which returns e.g. "Array" from the @@toStringTag) *interacting with old code* (which tests for "[object Array]") would be affected.

But in these cases developers have plenty of opportunities to test the interaction. And they quite probably are introducing the "Array" return value specifically to go down a specific code path in the old code. (For example, if they have created an array-like proxy that behaves like an Array in all other ways.) The current spec forces them to instead override Object.prototype.toString itself if they want to go down that path.

So I think the tilde-prefixing is certainly not necessary, and in fact is counterproductive in all cases I can think of.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Jordan Harband
Between the two issues I proposed, I definitely think that "something pretending to be a builtin" is far less hazardous then "altering builtins to appear to be something else". If removing the prefixing entirely is what it takes to make *all* (not just ES5) builtin @@toStringTag values non-configurable, I'd be happy with that.

That said, new code interacting with old code is indeed the hazard, since the old code won't know anything about ES6.

But in these cases developers have plenty of opportunities to test the interaction. And they quite probably are introducing the "Array" return value specifically to go down a specific code path in the old code. (For example, if they have created an array-like proxy that behaves like an Array in all other ways.) The current spec forces them to instead override Object.prototype.toString itself if they want to go down that path.
If it's a proxy to an actual array, wouldn't @@toStringTag be proxied too? If it's not a proxy to an actual array, why is the fact that it's a proxy relevant - it seems like your question is the same if you say "array-like object" also? Just to be sure I'm understanding. The real issue, as you've pointed out, is that there's no easy way to answer the question "does this value behave like an array" short of either ducktyping, or treating it like one, and seeing if it breaks. Let's fix that problem instead of allowing people to misuse @@toStringTag as an attempt to fake an answer to that question.

On Tue, Jan 20, 2015 at 11:45 AM, Domenic Denicola <[hidden email]> wrote:
From: es-discuss [mailto:[hidden email]] On Behalf Of Jordan Harband

> It appears that TC39 considers it important to not break existing JS code with spec changes. Thus, `Object.prototype.toString.call(foo)`, for any ES5 value "foo", must always and forever return the same value that it returned in ES5 - otherwise, existing code may follow different code paths in ES5 versus ES6, which is a hazard. This leads me to the belief that @@toStringTag values on ES5 builtins should never be changeable.

I don't think this reasoning, or in fact the reasoning that leads to the current tilde-prefixing, is sound.

First we must realize that if we were to remove the tilde-prefixing, no deployed code would ever break. Only new code (which returns e.g. "Array" from the @@toStringTag) *interacting with old code* (which tests for "[object Array]") would be affected.

But in these cases developers have plenty of opportunities to test the interaction. And they quite probably are introducing the "Array" return value specifically to go down a specific code path in the old code. (For example, if they have created an array-like proxy that behaves like an Array in all other ways.) The current spec forces them to instead override Object.prototype.toString itself if they want to go down that path.

So I think the tilde-prefixing is certainly not necessary, and in fact is counterproductive in all cases I can think of.



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Boris Zbarsky
On 1/20/15 3:13 PM, Jordan Harband wrote:
> Between the two issues I proposed, I definitely think that "something
> pretending to be a builtin" is far less hazardous then "altering
> builtins to appear to be something else". If removing the prefixing
> entirely is what it takes to make *all* (not just ES5) builtin
> @@toStringTag values non-configurable, I'd be happy with that.

I don't see how that solves the problem you're trying to solve.

Consider:

   var arr = [];
   Object.defineProperty(arr, Symbol.toStringTag,
                         { value: "Date" });

In today's spec, Object.prototype.toString.call(arr) will be "[object
~Map]".

If the ~-prefixing is removed, this will return "[object Date]", no?
The fact that @@toStringTag is non-configurable on Array.prototype
doesn't matter, since the above code shadows it on the instance.

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Dmitry Soshnikov
In reply to this post by Nicholas C. Zakas-3
A side note: while the `@toStringTag` topic is actively discussed and is planned for the following meeting, I'd like to double-check the topic I raised previously related to the `@toStringTag` and user-level classes: [1] (basically provide default `@@toStringTag` being the class name), and what Nicholas's use-case shows in his initial message in this thread.


Dmitry

On Mon, Jan 19, 2015 at 2:59 PM, Nicholas C. Zakas <[hidden email]> wrote:
According to 19.1.3.6 Object.prototype.toString() [1], it's possible to do this:

```js
function Foo(){}

Foo.prototype[Symbol.toStringTag] = "Null";

Object.prototype.toString.call(new Foo());   // "[object Null]"
```

It seems like `"Null"` and `"Undefined"` should be added to the step 17(b) list of exceptions to prevent spoofing of null and undefined values using this approach.

I couldn't think of a reason why the current behavior would make sense, but if I'm off base, feel free to correct me. :)

[1]: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring

--
___________________________
Nicholas C. Zakas
http://www.nczonline.net

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: @@toStringTag spoofing for null and undefined

Domenic Denicola
In reply to this post by Jordan Harband
From: Jordan Harband [mailto:[hidden email]]

> Between the two issues I proposed, I definitely think that "something pretending to be a builtin" is far less hazardous then "altering builtins to appear to be something else".

I don't think that's a hazard, any more than the mutability of the many other things you can already override is a hazard.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
In reply to this post by Mark S. Miller-2
Mark S. Miller wrote:

>
>
>     Yes, we want to complete the MOP so nominal types are equivalent
>     to branded structural types, a la Modula 3, and per David Ungar's
>     position articulated many times over the years (I heard David say
>     it to Tom Van Cutsem in person at SPLASH 2011, re: Proxies not
>     interceding fully for all types). But we aren't there yet.
>
>
> I don't understand this paragraph. Are you saying that you want a
> proxy to be able to intercept and emulate the brand check, while
> somehow preserving the integrity implied by the brand check?

I'm saying we (TC39, or many on it who've spoken up over the years)
aspire to make the JS MOP expressive enough to allow, e.g., implementing
bad old ES1-3 "host objects" via proxies, and even emulating primitive
or value types (value proxies, Cormac Flanagan et al.).

For some things such as the old WebIDL "caller" extended attribute,
which enabled document.all(id) in lieu of document.all[id], we've
instead trimmed licit (but not de-facto) host-object expressiveness to
remove the bad old thing.

IIRC David Ungar's question to Tom was "why not enable proxies to
mega-program every base-level operation in the language?" I took this to
mean nothing like a nominal type check could evade proxying, in David's
vision. Is this plausible in your view? Anyway, HTH.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Mark S. Miller-2


On Tue, Jan 20, 2015 at 2:19 PM, Brendan Eich <[hidden email]> wrote:
Mark S. Miller wrote:


    Yes, we want to complete the MOP so nominal types are equivalent
    to branded structural types, a la Modula 3, and per David Ungar's
    position articulated many times over the years (I heard David say
    it to Tom Van Cutsem in person at SPLASH 2011, re: Proxies not
    interceding fully for all types). But we aren't there yet.


I don't understand this paragraph. Are you saying that you want a proxy to be able to intercept and emulate the brand check, while somehow preserving the integrity implied by the brand check?

I'm saying we (TC39, or many on it who've spoken up over the years) aspire to make the JS MOP expressive enough to allow, e.g., implementing bad old ES1-3 "host objects" via proxies, and even emulating primitive or value types (value proxies, Cormac Flanagan et al.).

For some things such as the old WebIDL "caller" extended attribute, which enabled document.all(id) in lieu of document.all[id], we've instead trimmed licit (but not de-facto) host-object expressiveness to remove the bad old thing.

IIRC David Ungar's question to Tom was "why not enable proxies to mega-program every base-level operation in the language?" I took this to mean nothing like a nominal type check could evade proxying, in David's vision. Is this plausible in your view?

No it is not. It destroys the whole point of branding if passing a brand check guarantees nothing.


 
Anyway, HTH.

/be



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
In reply to this post by Brendan Eich-2
Brendan Eich wrote:
> IIRC David Ungar's question to Tom was "why not enable proxies to
> mega-program every base-level operation in the language?"

LOLtypo: "meta-" not "mega-", of course.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
In reply to this post by Mark S. Miller-2
Mark S. Miller wrote:
>
>     IIRC David Ungar's question to Tom was "why not enable proxies to
>     mega-program every base-level operation in the language?" I took
>     this to mean nothing like a nominal type check could evade
>     proxying, in David's vision. Is this plausible in your view?
>
>
> No it is not. It destroys the whole point of branding if passing a
> brand check guarantees nothing.

The counter-argument I inferred from the Q&A (this was in 2011, IIRC you
were there too ;-) would answer in two parts:

1. Needless-nominal type tests should be replaced by structural-type tests.

2. Any remaining brand or trademark test can use object identity or
equivalent unforgeable capability.

(2) can't be meta-programmed to spoof identity. But it doesn't leave
anything like nominal types as found in many languages lying around as
an attractive nuisance (and how, in Java!).

Now plausible?

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Brendan Eich-2
Brendan Eich wrote:
> 2. Any remaining brand or trademark test can use object identity or
> equivalent unforgeable capability.
>
> (2) can't be meta-programmed to spoof identity.

Reference identity, of course -- value types/proxies want value identity
defined by concatenating and freezing existing primitives, or equivalent.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: @@toStringTag spoofing for null and undefined

Mark S. Miller-2
In reply to this post by Brendan Eich-2
[+ungar, +tvcutsem]
 

On Tue, Jan 20, 2015 at 2:36 PM, Brendan Eich <[hidden email]> wrote:
Mark S. Miller wrote:

    IIRC David Ungar's question to Tom was "why not enable proxies to
    mega-program every base-level operation in the language?" I took
    this to mean nothing like a nominal type check could evade
    proxying, in David's vision. Is this plausible in your view?


No it is not. It destroys the whole point of branding if passing a brand check guarantees nothing.

The counter-argument I inferred from the Q&A (this was in 2011, IIRC you were there too ;-)


I was not there, but I talked to Tom soon afterward. CC'ing Dave and Tom, who's memory of their conversation may also be informative ;)

 
would answer in two parts:

1. Needless-nominal type tests should be replaced by structural-type tests.

2. Any remaining brand or trademark test can use object identity or equivalent unforgeable capability.

(2) can't be meta-programmed to spoof identity. But it doesn't leave anything like nominal types as found in many languages lying around as an attractive nuisance (and how, in Java!).

What I think I remember hearing from Tom is that Dave's main point, and the main argument with Tom, was precisely allowing proxies to intercede on === checks, in which case you wouldn't even have that as a reliable indicator.

 

Now plausible?

No.
 


/be



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
1234 ... 7