Open Bug 1516508 Opened 10 months ago Updated 9 months ago

Trying to play large flash games while AdBlock Plus extension is installed causes FireFox to enter an infinite loop, eventually using up all RAM and crashing

Categories

(WebExtensions :: Compatibility, defect, P2)

64 Branch
defect

Tracking

(firefox64 affected, firefox65 affected, firefox66 affected)

Tracking Status
firefox64 --- affected
firefox65 --- affected
firefox66 --- affected

People

(Reporter: z.edwin, Unassigned)

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0

Steps to reproduce:

Open Firefox
Install AdBlock Plus extension
Install Flash player
Go to a large flash game site Eg: https://armorgames.com/play/12275/raze-2
Allow use of flash player on site
Wait.


Actual results:

Firefox started to slow down, eventually freezing. When I looked into task manager, Firefox's RAM usage was over 4 GB and still increasing steadily which leads me to conclude that FireFox has entered an infinite loop


Expected results:

The game should have loaded and I should have been able to play.
Hi,
 I can reproduce this on the latest builds from all channels.
Thanks for reporting!
Status: UNCONFIRMED → NEW
Component: Untriaged → Compatibility
Ever confirmed: true
Product: Firefox → WebExtensions
Flags: needinfo?(lgreco)
Priority: -- → P2

Yesterday I took a look at this issue, follows some details related to what I've been able to identify, in particular which part of the webpage and of the AdBlockPlus extension are actually triggering the exponential memory usage (and then the resulting crash).

The infinite loop is actually triggered by the following HTML fragment included in the webpage mentioned in comment 0:

  ...
  <img src="" onerror="this.src=''; ..."/>
  ...

The img tag above triggers an infinite number of "error" events, and Firefox (as well as Chrome) shows an pretty high memory usage even without any extension installed, because the image will fail to load and on the error event it is going to trigger a new load that is going to fail as well.

On the other side, AdBlockPlus' content script subscribes a listener to the "error" event in its include.preload.js script:

document.addEventListener("error", event => {
    checkCollapse(event.target);
}, true);

and this listener generates an array of urls from the event.target and exchange a message with the extension background page using the browser.runtime.sendMessage API call:

function checkCollapse(element)
{
  ...
  let urls = getURLsFromElement(element);
  if (urls.length == 0)
    return;
  ...
  browser.runtime.sendMessage(
    {
      type: "filters.collapse",
      urls,
      mediatype,
      baseURL: document.location.href
    },
    collapse =>
      ...
  );
  ...
}

And so:

  • the webpage triggers an infinite number of "error" events

  • for every one of them AdBlockPlus will exchange a message with the background page

  • to exchange a message with the background page, Firefox has to allocate a number of objects
    (e.g. SavedFrame, Promise, PromiseDebugInfo, and StructureCloneHolder needed to send the message
    across the processes), and these objects have to stay around until the content script receive a
    response from the extension page.

From what I've observed, it seems that the pressure generated by these "error" events is so high that Firefox is creating more of the above objects (e.g. SavedFrame, Promise, PromiseDebugInfo, StructureCloneHolder etc.)
way faster than it is actually able to garbage collect them once they are not needed anymore.

The attached extension contains a minimal test extension and a minimal HTML page that are able to trigger this issue in a way that is similar enough to AdBlockPlus.

To reproduce the issue using the attached file:

$ tar xvf test-domerror-loop-memory-hog-issue.tar.bz2
...
$ cd test-domerror-loop-memory-hog-issue

## Trigger issue on the originally reported webpage

$ web-ext run -f firefox-nightly --pref "dom.ipc.processCount=1" -u https://armorgames.com/play/12275/raze-2

## Trigger issue in a minimal HTML page that reproduce the issue

$ web-ext run -f firefox-nightly --pref "dom.ipc.processCount=1" -u domerror-loop.html

# and then press the button in the HTML page (maybe after opening the memory reporter devtools panel 
# to be able to collect a baseline memory report and one more to compare it with the baseline).
Flags: needinfo?(lgreco)

Hi Andreas,
can we reach out the AdBlockPlus developers do make them aware of the issue described in comment 3?

Flags: needinfo?(awagner)

(In reply to Luca Greco [:rpl] from comment #3)

Yes, that makes sense as my monitoring of the RAM used by Firefox was fluctuating quite a bit as if firefox was attempting to fix the problem but there were more errors generated than Firefox can fix after the extension was installed. And yes, even before the extension was installed, Firefox was extremely slow on the website. Maybe we should change the category of this bug. The developers should focus on preventing infinite loops from happening and terminate any process that has been attempted more than a certain amount of times.

The developer has been notified.

Flags: needinfo?(awagner)

A workaround is on the way.

I just released Adblock Plus 3.4.3 that includes the workaround. You should no longer experience exponential memory usage or crashes in this scenario.

You need to log in before you can comment on or make changes to this bug.