On Tue, May 26, 2009 at 12:21 PM, Jim Blandy <j...@mozilla.com> wrote:
> In section 13.2, it would be nice to have a rationale for the > poisoned-accessor definitions for the "caller" and "arguments" properties of > function instances, like the note at the end of the description of the > CreateArgumentsObject algorithm (formerly 10.5, now 10.6?). > > (But perhaps it's too embarrassing to admit that they were once properties > of functions and not frames.) > In addition to the points made in Brendan's wonderfully informative message, I'll add one. JavaScript has one and only one encapsulation mechanism -- functions evaluating to closures that encapsulate their captured variables. However, the existence of these de-facto properties pokes a fatal hole in this mechanism, leaving us with no defensible boundary. By mandating that these properties be poisoned for strict functions, strict functions are mostly safe even from non-strict functions. The slides starting at < http://google-caja.googlecode.com/svn/trunk/doc/html/es5-talk/img39.html>, explained starting at 41minutes into < http://www.youtube.com/watch?v=Kq4FpMe6cRs> shows a simple vivid example. At the time I gave this talk, I thought it actually made strict functions safe from non-strict functions, without needing the "mostly" qualifier. However, since then, I have noticed a wide gaping hole remaining. When a (let's say) powerful strict function foo calls an untrusted non-strict function bar, then bar ideally should obtain access only to the arguments that foo explicitly passes to it. This being JavaScript, we all know that bar also obtains access to the "this" object that foo also effectively passed to it. (In the SES context, this is known as the "exophoric function problem", and can probably be worked around by low overhead translation.) The new hole I just noticed: Although foo's poisoned properties prevent bar from accessing foo's encapsulated variables, bar can still use the the de-facto "arguments.caller" or "bar.caller" to obtain access to foo itself. If the subsystem containing foo had wished to encapsulate foo itself, this reflection on bar's part violates the encapsulation of its calling subsystem. To fix this problem, we need one additional bit of poison: If arguments.caller or bar.caller would reveal a strict function, they should return something harmless instead. I suggest that undefined is a perfectly fine harmless value. If this poison is not swallowed, then SES can still cope by translating all function calls to go through a harmless laundry function: function laundry(obj, verb, args) { "use strict"; return obj[verb].apply(obj, args); } in which case bar.caller or bar's arguments.caller would simply return the harmless laundry instead. However, I would really like to avoid a translation that doubles the number of function calls performed. If undefined is, for some reason, not acceptable as a harmess value, then we could provide the above laundry function as if we had done this translation but without paying the cost. -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss