Section 13.2: Rationale for "caller", "arguments" restriction

Mark S. Miller erights at
Tue May 26 18:05:19 PDT 2009

On Tue, May 26, 2009 at 12:21 PM, Jim Blandy <jimb at> 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 <>,
explained starting at 41minutes into <> 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

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 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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list