<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[23991] trunk</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/23991">23991</a></dd>
<dt>Author</dt> <dd>antti</dd>
<dt>Date</dt> <dd>2007-07-04 15:54:49 -0700 (Wed, 04 Jul 2007)</dd>
</dl>

<h3>Log Message</h3>
<pre>LayoutTests:

        Reviewed by John.
        
        Test for Repro crash due to infinite recursion in HTMLParser::handleError @ youos.com
        &lt;rdar://problem/5237811&gt;

        * fast/table/incomplete-table-in-fragment-hang-expected.txt: Added.
        * fast/table/incomplete-table-in-fragment-hang.html: Added.

WebCore:

        Reviewed by John.
        
        Fix Repro crash due to infinite recursion in HTMLParser::handleError @ youos.com
        &lt;rdar://problem/5237811&gt;
        
        It is possible to add table parts (thead etc) without table ancestor to a document fragment. If a new table element
        was added to such a part, as in
        
        div.innerHTML = '&lt;tbody&gt;&lt;table&gt;';
        
        the parser error handling code would try to pop the previous table as normal. However since
        the table does not actually exist nothing would happen and parser would go to infinite recursion.
        
        Solution here is to pop table parts one by one when handling the error inside a fragment instead of trying to pop
        the table straight away (as it might not exist).

        * html/HTMLParser.cpp:
        (WebCore::HTMLParser::handleError):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkWebCoreChangeLog">trunk/WebCore/ChangeLog</a></li>
<li><a href="#trunkWebCorehtmlHTMLParsercpp">trunk/WebCore/html/HTMLParser.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasttableincompletetableinfragmenthangexpectedtxt">trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttableincompletetableinfragmenthanghtml">trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (23990 => 23991)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2007-07-04 21:57:56 UTC (rev 23990)
+++ trunk/LayoutTests/ChangeLog        2007-07-04 22:54:49 UTC (rev 23991)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2007-07-05  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Reviewed by John.
+        
+        Test for Repro crash due to infinite recursion in HTMLParser::handleError @ youos.com
+        &lt;rdar://problem/5237811&gt;
+
+        * fast/table/incomplete-table-in-fragment-hang-expected.txt: Added.
+        * fast/table/incomplete-table-in-fragment-hang.html: Added.
+
</ins><span class="cx"> 2007-07-04  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mitz.
</span></span></pre></div>
<a id="trunkLayoutTestsfasttableincompletetableinfragmenthangexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang-expected.txt (0 => 23991)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang-expected.txt        2007-07-04 22:54:49 UTC (rev 23991)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+Test error handling for incomplete tables inside a document fragment. These should not crash or hang. 
+
+&lt;tbody&gt;&lt;/tbody&gt;&lt;table&gt;&lt;/table&gt;
+&lt;thead&gt;&lt;/thead&gt;&lt;table&gt;&lt;/table&gt;
+&lt;tfoot&gt;&lt;/tfoot&gt;&lt;table&gt;&lt;/table&gt;
+&lt;tr&gt;&lt;/tr&gt;&lt;table&gt;&lt;/table&gt;
+&lt;td&gt;&lt;table&gt;&lt;/table&gt;&lt;/td&gt;
+&lt;th&gt;&lt;table&gt;&lt;/table&gt;&lt;/th&gt;
+&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;table&gt;&lt;/table&gt;
+&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;table&gt;&lt;/table&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/tbody&gt;
+&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;table&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
+&lt;tr&gt;&lt;td&gt;&lt;table&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;
+&lt;th&gt;&lt;table&gt;&lt;/table&gt;&lt;/th&gt;
+&lt;td&gt;&lt;table&gt;&lt;/table&gt;&lt;/td&gt;
+&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;table&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
+&lt;option&gt;&lt;/option&gt;&lt;table&gt;&lt;tbody&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table&gt;&lt;/table&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasttableincompletetableinfragmenthanghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang.html (0 => 23991)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang.html                                (rev 0)
+++ trunk/LayoutTests/fast/table/incomplete-table-in-fragment-hang.html        2007-07-04 22:54:49 UTC (rev 23991)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+&lt;body&gt;
+&lt;script&gt;
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+&lt;/script&gt;
+&lt;div id=inner&gt;&lt;/div&gt;
+Test error handling for incomplete tables inside a document fragment. These should not crash or hang.
+&lt;br&gt;&lt;br&gt;
+&lt;div id=console&gt;&lt;/div&gt;
+&lt;script&gt;
+
+var inner = document.getElementById('inner');
+var console = document.getElementById('console');
+
+function log(t)
+{
+    var line = document.createElement('div');
+    line.innerText = t;
+    console.appendChild(line);
+}
+
+inner.innerHTML = &quot;&lt;tbody&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;thead&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tfoot&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tr&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;td&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;th&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tbody&gt;&lt;tr&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tbody&gt;&lt;th&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tbody&gt;&lt;td&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tr&gt;&lt;tbody&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;th&gt;&lt;tbody&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;td&gt;&lt;tbody&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;tbody&gt;&lt;option&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+inner.innerHTML = &quot;&lt;table&gt;&lt;option&gt;&lt;table&gt;&quot;;
+log(inner.innerHTML);
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/ChangeLog (23990 => 23991)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/ChangeLog        2007-07-04 21:57:56 UTC (rev 23990)
+++ trunk/WebCore/ChangeLog        2007-07-04 22:54:49 UTC (rev 23991)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2007-07-05  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Reviewed by John.
+        
+        Fix Repro crash due to infinite recursion in HTMLParser::handleError @ youos.com
+        &lt;rdar://problem/5237811&gt;
+        
+        It is possible to add table parts (thead etc) without table ancestor to a document fragment. If a new table element
+        was added to such a part, as in
+        
+        div.innerHTML = '&lt;tbody&gt;&lt;table&gt;';
+        
+        the parser error handling code would try to pop the previous table as normal. However since
+        the table does not actually exist nothing would happen and parser would go to infinite recursion.
+        
+        Solution here is to pop table parts one by one when handling the error inside a fragment instead of trying to pop
+        the table straight away (as it might not exist).
+
+        * html/HTMLParser.cpp:
+        (WebCore::HTMLParser::handleError):
+
</ins><span class="cx"> 2007-07-04  Qing Zhao  &lt;qing@staikos.net&gt;
</span><span class="cx"> 
</span><span class="cx">         Reviewed by George Staikos.
</span></span></pre></div>
<a id="trunkWebCorehtmlHTMLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/html/HTMLParser.cpp (23990 => 23991)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/html/HTMLParser.cpp        2007-07-04 21:57:56 UTC (rev 23990)
+++ trunk/WebCore/html/HTMLParser.cpp        2007-07-04 22:54:49 UTC (rev 23991)
</span><span class="lines">@@ -510,6 +510,9 @@
</span><span class="cx">         } else if (h-&gt;hasLocalName(tableTag) || h-&gt;hasLocalName(trTag) || isTableSection(h)) {
</span><span class="cx">             if (n-&gt;hasTagName(tableTag)) {
</span><span class="cx">                 reportError(MisplacedTableError, &amp;currentTagName);
</span><ins>+                if (m_isParsingFragment &amp;&amp; !h-&gt;hasLocalName(tableTag))
+                    // fragment may contain table parts without &lt;table&gt; ancestor, pop them one by one
+                    popBlock(h-&gt;localName());
</ins><span class="cx">                 popBlock(localName); // end the table
</span><span class="cx">                 handled = true;      // ...and start a new one
</span><span class="cx">             } else {
</span></span></pre>
</div>
</div>

</body>
</html>