Open Bug 1148897 Opened 7 years ago Updated 2 years ago

Firefox freezes on a website due to too much recursion in JS script

Categories

(Core :: DOM: Core & HTML, defect, P3)

36 Branch
x86_64
Linux
defect

Tracking

()

People

(Reporter: tischuer, Unassigned)

References

(Depends on 1 open bug)

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
Build ID: 2015032000

Steps to reproduce:

Start Firefox and open this site:
http://print.wdr.de/2015-03/files/assets/basic-html/index.html#7

Then right-click on the page "18" link and choose "open in new tab" (or just open another tab with this site: http://print.wdr.de/2015-03/files/assets/basic-html/page18.html).



Actual results:

Firefox freezes (tested with the Windows-, openSUSE-, and Fedora versions of Firefox 36.0.4).

It seems to be an error in the JavaScript engine.


Expected results:

Show the webpage(s).
See https://support.mozilla.org/en-US/kb/firefox-hangs-or-not-responding for general info.

I cannot reproduce any such freeze with firefox-36.0.4-1.fc21.i686 on Fedora 21.

Webconsole shows "SecurityError: The operation is insecure" and a counter rapidly increasing for http://print.wdr.de/2015-03/files/assets/common/ecommerce/cart.js though.
Note that the upper right corner of the given link says "Basic HTML version".
Summary: Firefox freezes on a (popular german) website → Firefox freezes on a website
We(!) are able to reproduce this freeze on several (completely) different systems:

- Windows 8.1 (64-Bit)
- Two different systems with openSUSE 13.2 (64-Bit): One Intel Core i7 and one Core i5
- Fedora (don't know the exact system specs from my friend)
- Ubuntu 14.04 (in Virtualbox)
- openSUSE 13.2, 64-Bit with Firefox downloaded from Mozilla

In Windows 8.1 Firefox freezes the whole system (I had to do a hard reset).

Regarding the "Basic HTML version": Yes, that's right. The other version is the one with Flash. :)
The "Basic HTML version" works in Chrome, btw, and should work in Firefox.
Hmm. I admit asking for safe mode and for a fresh profile are the two "default" questions I ask on bug reports, but might still be helpful here in order to exclude some factors:

Does the problem still happen if you start Firefox in Safe Mode? (Safe Mode disables extensions and themes, hardware acceleration and some JavaScript stuff in order to exclude some possible reasons for problems. It does not disable plugins which are add-ons.) See http://support.mozilla.com/en-US/kb/Safe+Mode 

And does this also happen with a new and empty profile? See http://support.mozilla.com/en-US/kb/Basic%20Troubleshooting#w_8-make-a-new-profile and http://support.mozilla.org/kb/Managing%20profiles
I'm able to reproduce the freeze with FF36/39 on Win 7. FF uses a ton of CPU (~40%) during rendering and the memory spikes.
(In reply to Andre Klapper from comment #3)
> Does the problem still happen if you start Firefox in Safe Mode? 

Yes.

> And does this also happen with a new and empty profile? 

Yes.

Firefox does not freeze when I disable JavaScript (by setting "javascript.enabled" to "false"). That's the reason why I assume an error in the JavaScript engine.
The freeze is due to too much recursion in this JS script:
http://print.wdr.de/2015-03/files/assets/basic-html/javascript/seo.js (too much recursion seo.js:18:374)

If you block this file (with ABP eg), no more freeze.
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
Summary: Firefox freezes on a website → Firefox freezes on a website due to too much recursion in JS script
(In reply to Loic from comment #6)
> The freeze is due to too much recursion in this JS script:
> http://print.wdr.de/2015-03/files/assets/basic-html/javascript/seo.js (too
> much recursion seo.js:18:374)
> 
> If you block this file (with ABP eg), no more freeze.

So, that means: "Yes, it's a bug/problem in Firefox/JavaScript that needs to be fixed"?
> So, that means: "Yes, it's a bug/problem in Firefox/JavaScript that needs to be fixed"?

So the basic structure of this script is like this, stripping out various (maybe; unclear) irrelevant stuff:

  function f() {
    var b = document.getElementsByTagName("head")[0],
    a = document.createElement("script");
    a.type = "text/javascript";
    a.src = something; // This is cart.js
    b.appendChild(a);
    f();
  }

this is clearly buggy; that's not what it meant to do.  The interesting part is what happens after this.

In Chrome on Mac, this runs for about 15000 iterations, then runs out of stack and throws an exception.  During this time it has added 15000 <script> elements to the DOM.

In Firefox on Mac, this runs for about 150000 iterations (because we end up using less stack space per iteration than Chrome here), then runs out of stack and throws an exception.  So it adds 10 times as many <script> elements to the DOM.

You can test this on other operating systems, where the stack limits are likely different, using this script:

  <script>
  var depth = 0;
  function f() {
    ++depth;
    var b = document.getElementsByTagName("head")[0],
        a = document.createElement("script");
    a.type = "text/javascript";
    a.src = "data:text/javascript,";
    b.appendChild(a);
    f();
  }
  try {
    f();
  } catch(e) { alert(depth); }
  </script>

and I'd be interested to know what depth values you get on Windows...

For what it's worth, Chrome does freeze up for several hundred milliseconds on that testcase, so all else being equal we'd freeze up for several seconds, since we end up doing 10x the number of iterations.

That said, not all else is equal.  With this testcase:

  <script>
  var depth = 0;
  var j = 0
  function f() {
    ++depth;
    var b = document.getElementsByTagName("head")[0],
    a = document.createElement("script");
    a.type = "text/javascript";
    a.src = "data:text/javascript,++j";
    b.appendChild(a);
  }
  var start = new Date;
  var mid;
  onload = function() {
    var stop = new Date;
    alert("Time to create scripts: " + (mid - start) + 
          "\nTime to onload: " + (stop - start) + 
          "\nValue of j: " + j);
  }
  for (var i = 0; i < 100000; ++i) f();
  mid = new Date;
  </script>

we see that it takes us about 3x as long as Chrome to run through the initial loop creating all the <script> elements, and then a good long while (40x as long as Chrome) to run all the scripts.

So we should try to improve those things, obviously, but that will only help to bring the pause down from "10s of seconds" to "seconds" and the memory usage will still be huge.  Fixing _that_ requires either purposefully limiting our recursion depth or the site bug getting fixed.

Moving over to DOM for now to investigate that last testcase, but we may want to have a tech evangelism bug on the site itself to fix their bug...
Status: UNCONFIRMED → NEW
Component: JavaScript Engine → DOM
Ever confirmed: true
(In reply to Not doing reviews right now from comment #8)
> and I'd be interested to know what depth values you get on Windows...

On the 2015-03-30 Nightly in a clean profile (pasting the script in an otherwise blank .html file stored locally) I get the following values:

32-bit: 22555 or 22552
64-bit: 12932 or 12929

Results appear slightly non-deterministic, but those are the most common values.
And what about in Chrome on the same system?
Using the latest Chrome Canary from [1], which seems to always install the 64-bit version on my system regardless of which I choose to download: 15734

Using the latest Chromium snapshot from [2], which only appears to offer 32-bit builds for Windows: 31507

I don't know if these numbers are directly comparable, but they appear to be consistent across refreshes.

[1] https://www.google.com/chrome/browser/canary.html?platform=win64
[2] https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win/
Thanks.  So at least on Windows this is all down to the perf difference, not differences in recursion depth.
Depends on: 1149228
Depends on: 1149235
Depends on: 1149272
Depends on: 1149280
just drive-by to explore the "too much recursion" issue.
The specific URIs up there are not accessible anymore.

Two recent issues with similar messages AND jQuery 1.12.4
https://github.com/webcompat/web-bugs/issues/16716
https://github.com/webcompat/web-bugs/issues/16732
(but not necessary related).
Priority: -- → P3
Component: DOM → DOM: Core & HTML
See Also: → 1615147
You need to log in before you can comment on or make changes to this bug.