Fix for crash when assigning document.body

Maciej Stachowiak mjs at apple.com
Fri Oct 3 14:37:52 CEST 2003


This patch fixes two problems that led to a crash on this HTML:

<html>
<body>
<script>document.body = new Object</script>
</body>
</html>

First of all, setting a document body to null at the C++ level should 
be ignored, instead of removing the body, because that's what happens 
when the JavaScript bindings can't convert the argument to a node. 
Second, the HTML parser needs to keep the "current" node ref'd, since 
script execution can remove arbitrary nodes from the document while 
parsing.

-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/ChangeLog,v
retrieving revision 1.2050
diff -u -p -r1.2050 ChangeLog
--- ChangeLog	2003/10/02 23:28:33	1.2050
+++ ChangeLog	2003/10/03 07:34:01
@@ -1,3 +1,24 @@
+2003-10-03  Maciej Stachowiak  <mjs at apple.com>
+
+        Reviewed by NOBODY (OOPS!).
+
+	- fixed 3398420 - crash when creating a new document.body object in <body>
+	
+        * khtml/html/html_documentimpl.cpp:
+        (HTMLDocumentImpl::setBody): Don't remove the body when null is passed in,
+	as this means type error at the higher level and should be ignored.
+        * khtml/html/htmlparser.cpp:
+        (KHTMLParser::KHTMLParser): Initialize current to 0.
+        (KHTMLParser::setCurrent): Ref new current and deref old; we need to
+	keep it ref'd because script execution could drop the current node on the
+	floor.
+	(KHTMLParser::reset): Use setCurrent.
+        (KHTMLParser::insertNode): Likewise.
+        (KHTMLParser::reopenResidualStyleTags): Likewise.
+        (KHTMLParser::popOneBlock): Likewise.
+        (KHTMLParser::finished): Likewise.
+        * khtml/html/htmlparser.h: Prototype setCurrent.
+
 2003-10-02  David Hyatt  <hyatt at apple.com>
 
 	Remove the speed hit from using the UC break locators by not using them when
Index: khtml/html/html_documentimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_documentimpl.cpp,v
retrieving revision 1.46
diff -u -p -r1.46 khtml/html/html_documentimpl.cpp
--- khtml/html/html_documentimpl.cpp	2003/09/26 00:57:15	1.46
+++ khtml/html/html_documentimpl.cpp	2003/10/03 07:34:04
@@ -243,10 +243,10 @@ void HTMLDocumentImpl::setBody(HTMLEleme
 {
     int exceptioncode = 0;
     HTMLElementImpl *b = body();
-    if ( !_body && !b ) return;
-    if ( !_body )
-        documentElement()->removeChild( b, exceptioncode );
-    else if ( !b )
+    if ( !_body ) 
+	return;
+
+    if ( !b )
         documentElement()->appendChild( _body, exceptioncode );
     else
         documentElement()->replaceChild( _body, b, exceptioncode );
Index: khtml/html/htmlparser.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/htmlparser.cpp,v
retrieving revision 1.57
diff -u -p -r1.57 khtml/html/htmlparser.cpp
--- khtml/html/htmlparser.cpp	2003/09/25 00:37:35	1.57
+++ khtml/html/htmlparser.cpp	2003/10/03 07:34:05
@@ -111,7 +111,8 @@ public:
  *    element or ignore the tag.
  *
  */
-KHTMLParser::KHTMLParser( KHTMLView *_parent, DocumentPtr *doc)
+KHTMLParser::KHTMLParser( KHTMLView *_parent, DocumentPtr *doc) 
+    : current(0)
 {
     //kdDebug( 6035 ) << "parser constructor" << endl;
 #if SPEED_DEBUG > 0
@@ -141,7 +142,7 @@ KHTMLParser::KHTMLParser( DOM::DocumentF
     blockStack = 0;
 
     reset();
-    current = i;
+    setCurrent(i);
     inBody = true;
 }
 
@@ -161,7 +162,7 @@ KHTMLParser::~KHTMLParser()
 
 void KHTMLParser::reset()
 {
-    current = document->document();
+    setCurrent(document->document());
 
     freeBlock();
 
@@ -183,6 +184,15 @@ void KHTMLParser::reset()
     discard_until = 0;
 }
 
+void KHTMLParser::setCurrent(DOM::NodeImpl *newCurrent) 
+{
+    if (newCurrent) 
+	newCurrent->ref(); 
+    if (current) 
+	current->deref(); 
+    current = newCurrent; 
+}
+
 void KHTMLParser::parseToken(Token *t)
 {
     if (t->id > 2*ID_CLOSE_TAG)
@@ -310,7 +320,7 @@ bool KHTMLParser::insertNode(NodeImpl *n
             if (newNode == current)
                 popBlock(id);
             else
-                current = newNode;
+                setCurrent(newNode);
 #if SPEED_DEBUG < 2
             if(!n->attached() && HTMLWidget)
                 n->attach();
@@ -405,7 +415,7 @@ bool KHTMLParser::insertNode(NodeImpl *n
                 DOM::NodeImpl *newNode = head->addChild(n);
                 if ( newNode ) {
                     pushBlock(id, tagPriority[id]);
-                    current = newNode;
+                    setCurrent(newNode);
 #if SPEED_DEBUG < 2
 		    if(!n->attached() && HTMLWidget)
                         n->attach();
@@ -619,7 +629,7 @@ bool KHTMLParser::insertNode(NodeImpl *n
                         !flat && endTag[id] != DOM::FORBIDDEN)
                     {
                         pushBlock(id, tagPriority[id]);
-                        current = n;
+                        setCurrent(n);
                         inStrayTableContent = true;
                         blockStack->strayTableContent = true;
                     }
@@ -1396,7 +1406,7 @@ void KHTMLParser::reopenResidualStyleTag
         malformedTableParent = 0;
 
         // Update |current| manually to point to the new node.
-        current = newNode;
+        setCurrent(newNode);
         
         // Advance to the next tag that needs to be reopened.
         HTMLStackElem* next = elem->next;
@@ -1529,7 +1539,7 @@ void KHTMLParser::popOneBlock(bool delBl
     removeForbidden(Elem->id, forbiddenTag);
 
     blockStack = Elem->next;
-    current = Elem->node;
+    setCurrent(Elem->node);
 
     if (Elem->strayTableContent)
         inStrayTableContent = false;
@@ -1614,5 +1624,5 @@ void KHTMLParser::finished()
 {
     // This ensures that "current" is not left pointing to a node when the document is destroyed.
     freeBlock();
-    current = 0;
+    setCurrent(0);
 }
Index: khtml/html/htmlparser.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/htmlparser.h,v
retrieving revision 1.17
diff -u -p -r1.17 khtml/html/htmlparser.h
--- khtml/html/htmlparser.h	2003/07/17 19:49:39	1.17
+++ khtml/html/htmlparser.h	2003/10/03 07:34:05
@@ -97,6 +97,7 @@ public:
     DOM::DocumentPtr *docPtr() const { return document; }
 
 protected:
+    void setCurrent(DOM::NodeImpl *newCurrent);
 
     KHTMLView *HTMLWidget;
     DOM::DocumentPtr *document;


More information about the Khtml-devel mailing list