Closed Bug 1599617 Opened 6 years ago Closed 5 years ago

WindowGlobalChild doesn't correctly handle a null mWindowGlobal

Categories

(Core :: DOM: Navigation, defect, P2)

defect

Tracking

()

RESOLVED FIXED
Fission Milestone M5b

People

(Reporter: bzbarsky, Assigned: smacleod)

References

Details

This can be triggered from a web page by creating a very deep callstack and then spinning the event loop so the machinery involved in ContentChild::RecvConstructBrowser runs.

Then we call WindowGlobalChild::WindowGlobalChild (under which sets mWindowGlobal to null. Then we call BrowserChild::Init, which calls, via nsWebBrowser::Create and nsDocShell::CreateContentViewerForActor, nsDocShell::CreateAboutBlankContentViewer. This tried to set up a new inner window, but when we land in nsGlobalWindowOuter::SetNewDocument we take the early return here:

  if (!js::CheckRecursionLimitConservativeDontReport(cx)) {
    NS_WARNING("Overrecursion in SetNewDocument");
    return NS_ERROR_FAILURE;
  }

and hence never set up the inner window. This means nsGlobalWindowInner::Create is never called, and hence WindowGlobalChild::InitWindowGlobal is never called.

The caller does not notice this, because in nsWebBrowser::Create we ignore the return value from nsDocShell::CreateContentViewerForActor.

There's another attempt to set up an inner via nsPIDOMWindowOuter::EnsureInnerWindow but that also fails, which throws an exception out of ContentFrameMessageManager_Binding::get_content.

Then we press on, land in WindowGlobalChild::RecvLoadURIInChild, dereference the null mWindowGlobal, and crash.

Kris, since Nika is out, do you know who could look into this?

Flags: needinfo?(kmaglione+bmo)

(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #0)

Kris, since Nika is out, do you know who could look into this?

I guess me. Nika has been working on refactoring the ways we create WindowGlobal actors so we run into fewer situations like this, but we probably shouldn't wait on that to fix a crash.

Assignee: nobody → kmaglione+bmo
Fission Milestone: --- → M5
Flags: needinfo?(kmaglione+bmo)
Status: NEW → ASSIGNED
Priority: -- → P3

CreateContentViewerForActor() should to check if a WindowGlobal has been successfully bound. If not, then tear down the actor with WindowGlobalChild::Destroy()?

See bug 1599498 for a test case. Can we turn the test case into a new crashtest?

Assigning to smacleod.

Assignee: kmaglione+bmo → smacleod

P2 M5b because this is a possible crash that could affect dogfooders.

Fission Milestone: M5 → M5b
Priority: P3 → P2
See Also: → 1599498

This was fixed by https://phabricator.services.mozilla.com/D56820 for Bug 1589123.

Writing a crashtest using the test case from Bug 1599498 wasn't really feasible.

:nika, do you think it's still worth adding the check for if we have an mWindowGlobal and calling Destroy() in CreatecontentViewerForActor()? If so, how would you suggest exposing if mWindowGlobal is null or not?

Status: ASSIGNED → RESOLVED
Closed: 5 years ago
Flags: needinfo?(nika)
Resolution: --- → FIXED

You can tell if mWindowGlobal is null by calling WindowGlobalChild::GetWindowGlobal(), which will return nullptr if it's null.

Perhaps we could have WindowGlobalChild::Init return a guard object which will call Destroy() if mWindowGlobal is not set by the time it is dropped?

Flags: needinfo?(nika)

(In reply to :Nika Layzell (ni? for response) from comment #6)

You can tell if mWindowGlobal is null by calling WindowGlobalChild::GetWindowGlobal(), which will return nullptr if it's null.

Gah, right, totally missed that it already had a GetWindowGlobal(), should have searched instead of just looking in the .cpp, heh.

Perhaps we could have WindowGlobalChild::Init return a guard object which will call Destroy() if mWindowGlobal is not set by the time it is dropped?

My initial though to this was to add something like the following to the end of WindowGlobalChild::Init:

  return MakeScopeExit([self{RefPtr(this)}] {
    if (!self->GetWindowGlobal()) {
      self->Destroy();
    }
  });

But I'm not if I can do this/the return typing... Were you thinking some custom guard object? Do you know if there is anything already in the codebase I could use as an example?

Flags: needinfo?(nika)

Yeah, returning that from WindowGlobalChild::Init probably doesn't work super well.

There are only two callsites for WindowGlobalChild::Init which could possibly have a null WindowGlobal, so perhaps write the ScopeExits at those call-sites.

Flags: needinfo?(nika)
See Also: → 1635228
You need to log in before you can comment on or make changes to this bug.