Conventional Javascript Debugging is for Wimps
December 26th, 2005

Recently, Firefox has been maxing out my CPU “when I have more than three tabs open.” As is typical with bug reports from users, this one is very poorly worded and essentially useless. It turns out that that was not a good explanation of what was going on. I messed around a little more and figured out that the problem had these characteristics:

  • The CPU was maxed out on any page.
  • Thread #0 was the offending thread.
  • Firefox’s working set increased steadily while looking at ESPN.
  • Firefox eventually crashes with an A/V if the browser is left on ESPN.

Firefox CPU spike

I’m not sure if this is some strange interaction of my specific combination of extensions and settings, or if this happens for all Firefox users. This seems like a possible security vulnerability, but I can’t say one way or the other.

I suppose I could have downloaded and compiled the source code for Firefox to figure things out, but that was way more effort than I felt like giving. I did managed to debug and fix this issue for myself—without source or symbols—which I think makes for an interesting writeup.

Since the problem was on every page on the website, and continued after the page finished loading, I assumed it had to be a javascript or Flash problem (both of which are abused by ESPN to an irritating degree). I don’t even have the Flash plugin for Firefox installed, so that narrowed the scope of my investigation.

The first thing I did was try to debug the Javascript normally; this was hampered by several factors:

  • The Javascript debugger for Firefox, Venkman, hasn’t officially come out for version 1.5 yet. I’ve complained about broken extensions before, but let me just reiterate how stupid and unprofessional I think broken extensions are.
  • Although this kind person has done his own workaround for 1.5, it was either brought to its knees by the ESPN site or was broken by something else.

To summarize the story to this point, I had a (likely) javascript problem on a page I visit very frequently, coupled with a browser bug that maxed the CPU and made the issue difficult to diagnose through normal means.

I attached to Firefox.exe in Windbg and started randomly breaking in and checking on thread zero while the spike was in progress. Sometimes, frames in the js3250 module were on the stack:

0:009> ~0k
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f97c 6009db8b js3250!JSLL_MinInt+0x45e2
0012f9c8 6009cdd9 js3250!js_GetSrcNoteOffset+0x5358
0012f9f0 600c7c01 js3250!js_GetSrcNoteOffset+0x45a6
0012fa08 600856b5 js3250!js_GetScriptLineExtent+0x39e6
0012fa28 600b036f js3250!JS_NewStringCopyZ+0x44
0012fa40 600b3e93 js3250!js_FindProperty+0x26c5

The information for js3250 confirms (if the module name and the names of the export functions weren’t enough for you) that it is the Mozilla Javascript implementation.

0:009> lmv m js3250
start    end        module name
60080000 600e9000   js3250     (export symbols)
   C:\Program Files\Mozilla Firefox\js3250.dll
    Loaded symbol image file:
        C:\Program Files\Mozilla Firefox\js3250.dll
    Image path: C:\Program Files\Mozilla Firefox\js3250.dll
    Image name: js3250.dll
    Timestamp:        Fri Nov 11 20:05:34 2005 (43753FDE)
    CheckSum:         00073A1C
    ImageSize:        00069000
    File version:
    Product version:
    File flags:       0 (Mask 3F)
    File OS:          10004 DOS Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04e4
    CompanyName:      Netscape Communications Corporation
    ProductName:      NETSCAPE
    InternalName:     JS3240
    OriginalFilename: js3240.dll
    ProductVersion:   4.0
    FileVersion:      4.0
    FileDescription:  Netscape 32-bit JavaScript Module
    LegalCopyright:   Copyright Netscape Communications. 1994-96
    LegalTrademarks:  Netscape, Mozilla

All of this is reasonably good evidence that javascript is the right place to start. I took a look at the exports for js3250 (x js3250!* in Windbg) — it appeared as though this module was implemented as a few dozen C-style exports.

I thought that a logical thing to look for was an “execute a javascript function” function of some kind, and there were a few exports named some variation of “Call function.”

0:009> x js3250!*Call*Function*
6008541f js3250!JS_CallFunction (<no parameter info>)
60085464 js3250!JS_CallFunctionName (<no parameter info>)
600854ff js3250!JS_CallFunctionValue (<no parameter info>)

I set a breakpoint on all of these.

0:009> bm js3250!*Call*Function*
1: 6008541f @!!"js3250!JS_CallFunction"
2: 60085464 @!!"js3250!JS_CallFunctionName"
3: 600854ff @!!"js3250!JS_CallFunctionValue"

After resuming the program, I started hitting these breakpoints constantly. I did a sanity check and made sure that this didn’t occur on a cleaner site (google), and this was the case. I didn’t have any immediate success figuring out what script functions were being called. You can dig up the source for these API’s if you like, but I’m guessing that the script is already processed into different data structures by the time the javascript engine gets here.

I looked at some of the stacks when these functions were called, and I noticed this pretty far down:

0012fc7c 00534e18 js3250!JS_EvaluateUCScriptForPrincipals+0x70

I hoped this would lead me to some bits of javascript pointed to from nearby locations on the stack, so I set a breakpoint there. When it was hit, I started dumping out strings (using “dda @esp” and and “ddu @esp”) and found this:

As an only slightly educated guess, I used the Adblock extension to block this script.

adblocking a single script

After reloading the page, the problem was gone! There don’t seem to be any site-breaking problems associated with turning this script off. This is all or part of the “ESPN Motion” business that tries to display sound and video on the site. Hey, ESPN: this is a terrible idea in the first place. Your website shouldn’t start yelling at me when I visit it. It’s no excuse for Firefox to A/V, but I thought everyone with a three-digit IQ stopped doing this in 1996.