js/xpconnect/crashtests/786142-iframe.html

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <script>
     6 // Morph a slim wrapper into an XPCWN by generating a cross-compartment wrapper
     7 // for it (we Morph in WrapperFactory::PrepareForWrapping).
     8 function makeNonSlim(elem) {
     9   window.parent.someCCW = elem;
    10   delete window.parent.someCCW;
    11 }
    13 function doTest() {
    15   // Get a slim wrapper for |form|. This lives in scope 1.
    16   var form = document.getElementById('myform');
    18   // The gist here is that we want to create an input element that isn't part
    19   // of a form, so that its PreCreate hook will cause it to be parented to the
    20   // document. However, there are several considerations that make this more
    21   // complicted.
    22   //
    23   // First, the crashtest becomes non-deterministics if we morph |form| before
    24   // getting to scope 3 (as explained below). This means that we can't trigger
    25   // the PreCreate hook for |input|, because that will call WrapNativeParent
    26   // on the form, which will end up making a cross-compartment wrapper, which
    27   // will morph form. But this puts us in a pickle, because appendChild returns
    28   // the apppended child, which will trigger the PreCreate hook in
    29   // NativeInterface2JSObject. So we do this little hack where we append a buch
    30   // of dummy <div> children to the form, and use replaceChild (which returns
    31   // the replacer, not the replacee) to stick the input elements as children of
    32   // the form.
    33   //
    34   // Second, the crashtest can also be non-deterministics if the final call to
    35   // MoveWrappers iterates over the hashtable in such a way that it fixes up
    36   // the Document before it fixes up the Input. If so, the Input will become
    37   // orphaned, and we'll detect it and fix things up at the top of MoveWrapper.
    38   // Since we can't control the hashtable ordering here, we just make 100 input
    39   // elements, to make it a near-certainty (statistically) that we'll encounter
    40   // one of them during iteration before encountering the Document.
    41   //
    42   // With all this, this testcase deterministically crashes on my machine. Whew!
    44   // Create an input element. This isn't part of a form right now, so it gets
    45   // parented to the document.
    46   var inputs = [];
    47   var placeHolders = [];
    48   for (var i = 0; i < 100; ++i) {
    49     var dummyDiv = form.appendChild(document.createElement('div'));
    50     var input = document.createElement('input');
    51     makeNonSlim(input);
    52     inputs.push(input);
    53     placeHolders.push(dummyDiv);
    54   }
    56   // Blow away the document, forcing a transplan of all the XPCWNs in scope. This
    57   // will transplant |input|, but |form| stays in the old scope (since it's slim).
    58   document.open();
    59   document.close();
    61   // Now we're in scope 2. Associate |input| with |form| so that the next call to
    62   // PreCreate will parent |input| to |form| rather than the document. But make
    63   // sure to do it with replaceChild, rather than appendChild, so that we don't
    64   // end up triggering the PreCreate hook for |form| in scope 2, which would make
    65   // make it non-slim. If we didn't, the ensuing call to MoveWrappers might find
    66   // |form| before |input| while iterating over the hashtable. If so, |form|
    67   // would be rescued as an orphan and everything would be fixed before getting to  // |input|.
    68   for (var i = 0; i < inputs.length; ++i)
    69     form.replaceChild(inputs[i], placeHolders[i]);
    71   // Blow away the document a second time. This should cause the crash in
    72   // unpatched builds.
    73   document.open();
    74   document.close();
    75 }
    76 </script>
    77 </head>
    78 <body>
    79 <form id="myform"></form>
    80 </body>
    81 </html>

mercurial