API to get stack frame info from generator

Mark S. Miller erights at google.com
Sat Jun 15 19:57:26 PDT 2013


On Sat, Jun 15, 2013 at 6:56 PM, Mark S. Miller <erights at google.com> wrote:

> On Sat, Jun 15, 2013 at 10:17 AM, David Bruant <bruant.d at gmail.com> wrote:
>
>> Le 15/06/2013 11:18, Bruno Jouhier a écrit :
>>
>>  A generator object represents a computation which has been suspended. We
>>> have an API to resume this computation (next/throw). What's missing is an
>>> API to get information about this suspended computation (which function,
>>> where in the source).
>>>
>> As an aside, note that we already have this sort of problem today with
>> event loop turns.
>>
>>     function schedule(){
>>         if(Math.random() < 0.5)
>>             throw new Error('whatever');
>>         else
>>             setTimeout(schedule, Math.random()*100);
>>     }
>>
>>     setTimeout(schedule, (Math.random()*100) |0)
>>     setTimeout(schedule, (Math.random()*100) |0)
>>
>> There is no way to know how many scheduling happened before the first
>> thrown error, nor whether the error comes from the first or second
>> scheduling originally. And that's a dummy 5-line example. It gets worse
>> when you have a sequence of different events (or promise resolutions)
>> called at different times, adding other listeners, etc.
>> Q solves that with long stack traces [1] (only for promises I believe).
>> It might be worth looking into it.
>>
>>
>> Back to your problem, I worry that this kind of information (a call to
>> get the stack trace of where the generator last yielding with line number)
>> may partially break encapsulation which wouldn't be good for security.
>> I'm thinking of something like:
>>
>>     (exports => {
>>         var someCrucialInfo = // boolean
>>
>>         exports.bla = function*(){
>>             if(someCrucialInfo){
>>                 doX();
>>                 yield 27;
>>             }
>>             else{
>>                 doY();
>>                 yield 27;
>>             }
>>         }
>>     })(this);
>>
>>     var v = this.bla();
>>     var l = getLastBlaYieldLine(bla);
>>     // given l, the encapsulated value of someCrucialInfo can be inferred
>>
>> cc'ing MarkM to get his eyes on it as I don't feel qualified to assess
>> the gravity.
>>
>
> Thanks for calling my attention to this thread. Generators and multiple
> turns aside (see below), we've been over the security issue before but a
> recap is useful. The stack trace information cannot be publicly accessible
> from the Error object because it violates encapsulation. (Historical note:
> When E entered its first security review, it had this vulnerability. Thanks
> to David Wagner for catching it.) Instead, some sort of rights
> amplification is required. One possible interface is a privileged function,
> like the getStack function at <
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js#221>,
> where
>
> getStack(err) returns the stacktrace. If you don't have the getStack
> function, you can't get the stacktrace. getStack is implemented using a
> WeakMap associating Errors with stacktraces.
>
> Another approach, if <
> http://wiki.ecmascript.org/doku.php?id=strawman:relationships> are
> adopted in ES7, is to have a relationship associating Error objects with
> stacktraces. The full read/write relationship would be internal to the
> implementation, but a relationship representing a readonly facet of that
> relationship, say @stacktrace, could be made available in the same
> privileged manner as getStack above. Then
>
> err at stacktrace would return the same stacktrace that getStack(err) would
> return above.
>
> If relationships don't happen in ES7 (it's too late for ES6) and private
> symbols do, then @stacktrace could be a private symbol.
>
>
>
> Multiple turn distributed debugging is indeed the next frontier, and one
> that will become ever more urgent as promises continue to catch on. I
> participated in a cool project, Causeway, that explored some of this
> territory well
> http://www.hpl.hp.com/techreports/2009/HPL-2009-78.html
> https://code.google.com/p/causeway/
>
> Although the project has since been abandoned, its trace log format is a
> good place to start, in order to be able to support something like this in
> the future:
> http://wiki.erights.org/wiki/Causeway_Platform_Developer
> http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Ajax
> http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Promises
>
>
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js
> also provides some support for the Causeway log format. See getCWStack.
>
> See also
> http://crpit.com/confpapers/CRPITV135Murray.pdf and
> http://infoscience.epfl.ch/record/181543/files/EPFL_TH5533.pdf
> for other interesting approaches to extended debugging
>
>
> As for generators specifically, it seems to me that whatever rights
> amplification operation one applies to an Error object to get a stack
> trace, one should also be able to apply to a generator instance to get a
> 1-level stacktrace showing where it is currently suspended.
>

Although these 1-level generator stacks aren't part of a larger synchronous
stack, they are part of the overall causality graph that Causeway tries to
trace. It would be interesting to think about where these would go in a
Causeway log, or if the Causeway log format would need to be extended to
accommodate this.



>
>
>
>> oh... and we have the source code of functions by default with
>> Function#toString.
>> This sort of inference can happen in regular error stack traces too, but
>> requires for a function to throw which happens only if it's supposed to,
>> not at the caller's will.
>> Though I realize now that anyone holding a reference to a generator can
>> force an error being thrown and, if uncaught, it generates a stack trace
>> leaking the line number even without the API you're asking for (but that
>> would work only once)
>>
>>
>>  I see this as being similar to asking for a portable "stack" property in
>>> Error objects. I don't know if it is actually mandated by ES6 but it looks
>>> like all major JS engines support it now.
>>>
>> I believe the state of TC39 on Error#stack can be found at
>> http://wiki.ecmascript.org/**doku.php?id=strawman:error_**stack<http://wiki.ecmascript.org/doku.php?id=strawman:error_stack>
>>
>> David
>>
>> [1] https://github.com/kriskowal/**q#long-stack-traces<https://github.com/kriskowal/q#long-stack-traces>
>>
>
>
>
> --
>     Cheers,
>     --MarkM
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130615/136bb758/attachment-0001.html>


More information about the es-discuss mailing list