On 9/11/17 7:41 AM, Henri Sivonen wrote:
Frame construction runs recursive algorithms along the depth of the
DOM tree.

It's not just frame construction. Recursive algorithms are all over the place in layout and DOM code.

Frame construction may be a long pole here in terms of crashes due to a combination of several things:

1) Largish stack frames (not least because it stores a bunch of state in RAII things).

2) Frame construction itself having a depth check in ProcessChildren that prevents the frame tree from getting too deep (though it really only limits the depth the frame constructor itself is willing to go to).

3) Layout having a separate IsFrameTreeTooDeep check that makes it stop reflowing descendants at some point.


There are three areas where changes could be made:
  1) We could re-calibrate the depth limit.
  2) The HTML parser could try harder to make the DOM rewrites keep
text nodes visible.
  3) The frame constructor could switch from a full-features recursive
algorithm to an iterative text node-only traversal near the depth
limit.

Option #3 won't really help with the third check I list above. Maybe we'll construct frames for all the content, but we still won't lay it out, hence it won't be visible.

I'd expect text node recovery (flattening out elements and just
considering text nodes) in the frame constructor to be a more robust
solution than trying to address the problem in the HTML parser. What's
the feasibility of such a frame constructor change?

Just doing that for initial construction is probably not too terrible.

Making it behave correctly (read: not crash exploitably) in the face of dynamic mutations is pretty hard, because it would violate various layout and frame constructor invariants. It might be more tractable than it used to be because maybe we can pretend like things are display:contents or something, but that means still doing stuff for all the ancestors of the textnodes, and in a non-recursive way. It might be doable, though.

My findings from testing with a very high limit so far are as follows:

What testcases were used? The actual stack depth needed for frame construction and layout is highly styling-dependent, because it affects what codepaths are taken. For example, I would expect something like this:

  <!DOCTYPE html>
  <div><div>....

To need less stack than something like this:

  <!DOCTYPE html>
  <style>div { display: table-cell }</style>
  <div><div>....

  * Windows 64-bit: between 740 and 750.
  * 32-bit Firefox on 64-bit Windows 10: between 500 and 510.
  * 32-bit Firefox on 64-bit Windows 7: between 510 and 520.

Were those measurements done with PGO builds? We need to make sure we do that, because PGO builds have quite different (and larger) stack frame sizes.

As for other browsers:
I didn't find a depth limit for Chrome. (Tried up to 16000.)

Which version of Chrome? Per comments in https://bugzilla.mozilla.org/show_bug.cgi?id=485941 at least in their XML parser they do have a depth limit of about 5000, but that was apparently removed and then readded recently. Of course they may have different behavior for XML and HTML.

OK if I change the limit on a per-OS basis according to these numbers?

I'd really like to see testcases with: 1) Lots of nested inlines instead of lots of nested blocks and 2) my display:table-cell stress test to see what the numbers look like then.

-Boris
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to