domenic at domenicdenicola.com (2013-08-29T19:25:34.476Z)
Btw, the problem this code illustrates is a problem Brendan pointed out to me at the last TC39 meeting.
Btw, the problem this code illustrates is a problem Brendan pointed out to me at the last TC39 meeting.
On Thu, Aug 22, 2013 at 8:04 AM, Mark S. Miller <erights at google.com> wrote: > On Wed, Aug 21, 2013 at 10:22 PM, Tab Atkins Jr. <jackalmage at gmail.com>wrote: > >> On Wed, Aug 21, 2013 at 5:55 PM, Mark S. Miller <erights at google.com> >> wrote: >> > On Wed, Aug 21, 2013 at 5:33 PM, Tab Atkins Jr. <jackalmage at gmail.com> >> > wrote: >> >> >> >> On Wed, Aug 21, 2013 at 5:12 PM, Mark S. Miller <erights at google.com> >> >> wrote: >> >>> On Wed, Aug 21, 2013 at 3:44 PM, Tab Atkins Jr. <jackalmage at gmail.com >> > >> >>> wrote: >> >>>> But I like just Promise(), sans "new". >> >>> >> >>> Good. I like it too, and Allen's latest draft class semantics enables >> >>> the >> >>> definition of classes that can do this reliably. But is there any way >> to >> >>> reliably polyfill this in ES5? It's not clear. For the std promise >> API, >> >>> given the urgency with which people want to use it *now*, I think this >> >>> polyfillability is important. >> >> >> >> Yes, why wouldn't it be? The test for promise-ness can be done today, >> >> without special browser privilege, and distinguishing between >> >> `Promise(foo)` and `new Promise(foo)` is a trivial matter of testing >> >> the type of `this` inside the function. (If it's instanceof Promise, >> >> you were called with new. Otherwise, you weren't. This isn't 100%, >> >> as people can fool you with Promise.call(), but that's not something >> >> you need to actually worry about, I think.) >> > >> > >> > This is an example of what I am worried about. Another is >> > >> > Object.create(p, {value: Promise}).Promise(....) >> > >> > where p is a promise. >> >> I'm not quite sure what this is supposed to do, because it's invalid >> Object.create. (Or rather, it creates a property named "value" with >> default descriptors, which I'm sure isn't intended.) >> > > You're right, my code is wrong. What I meant is: > > > Object.create(p, {Promise: {value: Promise}}).Promise(....) > > In other words, the Promise constructor might get supplied as its "this" > an object that passes "p instanceof Promise" for innocent reasons other > that "new" or .call. The question is, what does the Promise constructor > test in order to determine whether it should use its coercion behavior or > constructor behavior. If the test were "p instanceof Promise", then the > above call, which was clearly intending to invoke its coercion behavior, > would accidentally invoke its constructor behavior instead. > Btw, the problem this code illustrates is a problem Brendan pointed out to me at the last TC39 meeting. > > > >> >> > Perhaps it would help if, when we start to think "people can fool you >> > with..." it would help to substitute "an attacker can fool you with...". >> >> What exactly is the attack scenario being envisioned here, though? >> > > The promise constructor must create initialize and return trustworthy > promises, and it must not mark as trustworthy a promise that isn't. The > promise coercer must return trustworthy promises. If given an object > returned by the promise constructor or the promise coercer, the promise > coercer must return that object. > > > >> Okay, you can call a function and supply your own `this` value. And? >> You can always do this, before or after construction. > > > If we weren't trying to put both coercing and constructing behavior into > one function, switched on some unreliable test, then there wouldn't be a > new problem. Postponing subclassing till ES6 when we have the needed > support, the Promise constructor could just create and return a new > trustworthy promise (just as the first branch of the "solution" I present > below does). Promise.as would simply be the conditional we discussed > earlier (and corresponds to the second branch of the "solution" below). But > if we put these two behaviors in one function, what test do we use to > choose between them? > > > >> I don't think >> this lets you fool anything, because you, the attacker, have to run >> your own code to make it happen. > > > The attacker does run their own code. > > >> You can't somehow trick the defender >> into creating a tricky not-quite-authentic Promise, unless you've >> tricked them into using eval() or something. If the attacker is >> getting to run code of its choosing, you've already lost. >> > > Uh, Tab, attackers always run code of their choosing. But they don't run > that code with authority of their choosing. In an ocap system like SES, > "eval" provides no authorities by default. See > > <http://theory.stanford.edu/~ataly/Papers/sp11.pdf> > <http://erights.org/talks/thesis/markm-thesis.pdf> Part II, > <http://research.google.com/pubs/pub40673.html> section 2.3, > and the "video" and "slides" links at < > http://mobicrant-talks.eventbrite.com/> > > > >> >> Am I missing some obvious attack? >> > > Obvious perhaps only if you've been thinking about this kind of thing. > Please have a look at those links. > > > In any case, postponing subclassing till ES6 when we have the needed > support, I think I know how to "solve" the problem. It is a bit weird. > > var Promise = (function(){ > "use strict"; // of course > > var brand = new WeakMap(); > > // only ever called with "new" > function HiddenPromiseConstructor(callback) { > // initialize "this", which it can assume starts fresh and > trustworthily uninitialized > brand.set(this, true); > } > > function Promise(arg) { > if (Object.getPrototypeOf(this) === Promise.prototype && > !(brand.has(this))) { > // assume likely called with "new", but do not trust "this" > return new HiddenPromiseConstructor(arg) > } else { > // assume called for coercion behavior. Ignore this > if (brand.has(arg)) { > return arg; > } else { > return Promise.of(arg); > } > } > } > HiddenPromiseConstructor.prototype = Promise.prototype; > > // initialize Promise.prototype > // initialize Promise statics > return Promise > })(); > > > >> >> ~TJ >> > > > > -- > Cheers, > --MarkM > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130822/0998e443/attachment.html>