Closed Bug 686587 Opened 13 years ago Closed 6 years ago

Capture JS stack when an exception is thrown

Categories

(Core :: JavaScript Engine, defect)

Other Branch
x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 996060

People

(Reporter: jorendorff, Unassigned)

References

Details

We capture a stack when an Error object is created, but not when other values (such as DOM errors) are thrown. This makes it impossible to recover what happened later, or even right after unwinding the stack, when we want to display the error in the console, etc. It's really horrible.

We should stash a stack in the cx. Or something. There are some details to deal with, like when it's all right to throw the stack away.
Oh, another thing this might solve.

The Error.stack property is intentionally truncated when the stack-walking code reaches a cross-compartment boundary. This makes add-on development using Sandboxes painful.

But I think the reason it's truncated is just because it's visible to content, and there might be security issues. If we capture a stack that isn't JS-visible (or, not without using a Debugger object or some other chrome-only knob) then we don't have that limitation and we can show the whole stack.
Mike Ratcliffe points out that window.onerror only gets an error message, URL, and line number. It sure would be nice if it got the stack or something. Of course we would have to censor some stack frames and values--doable, I imagine.
mrbkap: I was told to CC you to this bug about comment 1. The thing is that for addon development it would be great to have the whole stack info across cross-compartment boundaries (not just for exceptions). But I have no clue how could I get that info once the previous frame is in a stored state...
(In reply to Jason Orendorff [:jorendorff] from comment #1)
> But I think the reason it's truncated is just because it's visible to
> content, and there might be security issues. If we capture a stack that
> isn't JS-visible (or, not without using a Debugger object or some other
> chrome-only knob) then we don't have that limitation and we can show the
> whole stack.

We chop off the stack for the case when chrome calls into content using a SJOW... In that case, we want to protect the chrome code from being inspected by content (and also to avoid "hacking" via arguments.callee.caller.caller...). Over in bug 668558, Luke proposed removing subsumes, but this seems to be a case where we only want to cut off the stack of the current compartment doesn't subsumes the previous compartment.
(In reply to Blake Kaplan (:mrbkap) from comment #6)

Perhaps you are talking about different stack-walking code, but InitExnPrivate cuts off the stack when either (1) a different compartment is reached or (2) JS_GetSecurityCallbacks->checkAccess says 'no'.  Is (2) implemented in terms of subsumes?

This does raise the issue that, with c-p-g, InitExnPrivate would cut off cross-global-but-same-origin exception stacks.  This could be pretty easily fixed by wrapping the values.
(In reply to Luke Wagner [:luke] from comment #7)
> Perhaps you are talking about different stack-walking code, but
> InitExnPrivate cuts off the stack when either (1) a different compartment is
> reached or (2) JS_GetSecurityCallbacks->checkAccess says 'no'.  Is (2)
> implemented in terms of subsumes?

Indirectly, yes it is (see nsScriptSecurityManager::CheckObjectAccess and note that nsScriptSecurityManager::CheckPropertyAccess basically uses Subsumes). I was thinking more about the code that allows us to walk the stack via arguments.caller.callee, but IMO these two stack walking codepaths should be parallel in terms of the security story/what they expose.

> This does raise the issue that, with c-p-g, InitExnPrivate would cut off
> cross-global-but-same-origin exception stacks.  This could be pretty easily
> fixed by wrapping the values.

Yes, but there is a security question to ask: we want to expose stacks that are same origin or less (i.e. subsumes).
Ah, so there is.  Do you think that checkAccess subsumed by subsumes?  A quick grep shows a bunch of cases that I would have to think pre-date compartments+wrappers and perhaps could be simply removed now.
That sounds right to me.
Depends on: 551604
Blocks: 551604
No longer depends on: 551604
I desperately need this for Jetpack dev (bug 551604 comment 14 and 16).
How can I help to get this fixed?
Assignee: general → nobody
DUP-ing forward to a slightly newer bug that has patches in it.
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.