diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp
index 04d6f1acdb57..8bed7559e85b 100644
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -100,6 +100,7 @@ public:
 
   nsresult Init(nsIDocument* aDoc, nsIURL* aURL, nsIWebWidget* aWebWidget);
   nsIHTMLContent* GetCurrentContainer(eHTMLTags* aType);
+  nsIHTMLContent* GetTableParent();
 
   virtual PRBool SetTitle(const nsString& aValue);
 
@@ -187,6 +188,12 @@ protected:
 
   nsresult AddText(const nsString& aText, nsIHTMLContent** aContent);
 
+  void AppendToCorrectParent(nsHTMLTag aParentTag,
+                             nsIHTMLContent* aParent,
+                             nsHTMLTag aChildTag,
+                             nsIHTMLContent* aChild,
+                             PRBool aAllowReflow);
+
   void GetAttributeValueAt(const nsIParserNode& aNode,
                            PRInt32 aIndex,
                            nsString& aResult);
@@ -731,7 +738,9 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode)
       }
 #endif
       
-      parent->AppendChild(container,  allowReflow);
+      AppendToCorrectParent(parentType, parent,
+                            (nsHTMLTag) aNode.GetNodeType(), container,
+                            allowReflow);
 #ifdef NS_DEBUG
       if (allowReflow && (((PRInt32)gSinkLogModuleInfo->level) > 127)) {
         PRInt32 i, ns = mDocument->GetNumberOfShells();
@@ -1051,10 +1060,12 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
 #ifdef NS_DEBUG
         if (allowReflow) {
           SINK_TRACE(SINK_TRACE_REFLOW,
-                     ("HTMLContentSink::CloseContainer: reflow after append"));
+                     ("HTMLContentSink::AddLeaf: reflow after append"));
         }
 #endif
-        parent->AppendChild(leaf, allowReflow);
+        AppendToCorrectParent(parentType, parent,
+                              (nsHTMLTag) aNode.GetNodeType(), leaf,
+                              allowReflow);
       } else {
         // XXX drop stuff on the floor that doesn't have a container!
         // Bad parser!
@@ -1066,6 +1077,107 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
   return 0;
 }
 
+// Special handling code to push unexpected table content out of the
+// table and into the table's parent, just before the table. Because
+// the table is a container, it will not have been added to it's
+// parent yet so we can just append the inappropriate content.
+void
+HTMLContentSink::AppendToCorrectParent(nsHTMLTag aParentTag,
+                                       nsIHTMLContent* aParent,
+                                       nsHTMLTag aChildTag,
+                                       nsIHTMLContent* aChild,
+                                       PRBool aAllowReflow)
+{
+  nsIHTMLContent* realParent = aParent;
+
+  // These are the tags that are allowed in a table
+  static char tableTagSet[] = {
+    eHTMLTag_tbody, eHTMLTag_thead, eHTMLTag_tfoot,
+    eHTMLTag_tr, eHTMLTag_col, eHTMLTag_colgroup,
+    eHTMLTag_caption,/* XXX ok? */
+    0,
+  };
+
+  // These are the tags that are allowed in a tbody/thead/tfoot
+  static char tbodyTagSet[] = {
+    eHTMLTag_tr,
+    eHTMLTag_caption,/* XXX ok? */
+    0,
+  };
+
+  // These are the tags that are allowed in a colgroup
+  static char colgroupTagSet[] = {
+    eHTMLTag_col,
+    0,
+  };
+
+  // These are the tags that are allowed in a tr
+  static char trTagSet[] = {
+    eHTMLTag_td, eHTMLTag_th,
+    0,
+  };
+
+  switch (aParentTag) {
+  case eHTMLTag_table:
+    if (0 == strchr(tableTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_tbody:
+  case eHTMLTag_thead:
+  case eHTMLTag_tfoot:
+    if (0 == strchr(tbodyTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_col:
+    realParent = GetTableParent();
+    break;
+
+  case eHTMLTag_colgroup:
+    if (0 == strchr(colgroupTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_tr:
+    if (0 == strchr(trTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  realParent->AppendChild(aChild, aAllowReflow);
+}
+
+// Find the parent of the currently open table
+nsIHTMLContent*
+HTMLContentSink::GetTableParent()
+{
+  PRInt32 sp = mStackPos - 1;
+  while (sp >= 0) {
+    switch (mNodeStack[sp]) {
+    case eHTMLTag_table:
+    case eHTMLTag_tr:
+    case eHTMLTag_tbody:
+    case eHTMLTag_thead:
+    case eHTMLTag_tfoot:
+    case eHTMLTag_col:
+    case eHTMLTag_colgroup:
+      break;
+    default:
+      return mContainerStack[sp];
+    }
+    sp--;
+  }
+  return mBody;
+}
+
 nsresult
 HTMLContentSink::AddText(const nsString& aText, nsIHTMLContent** aContent)
 {
diff --git a/layout/html/document/src/nsHTMLContentSink.cpp b/layout/html/document/src/nsHTMLContentSink.cpp
index 04d6f1acdb57..8bed7559e85b 100644
--- a/layout/html/document/src/nsHTMLContentSink.cpp
+++ b/layout/html/document/src/nsHTMLContentSink.cpp
@@ -100,6 +100,7 @@ public:
 
   nsresult Init(nsIDocument* aDoc, nsIURL* aURL, nsIWebWidget* aWebWidget);
   nsIHTMLContent* GetCurrentContainer(eHTMLTags* aType);
+  nsIHTMLContent* GetTableParent();
 
   virtual PRBool SetTitle(const nsString& aValue);
 
@@ -187,6 +188,12 @@ protected:
 
   nsresult AddText(const nsString& aText, nsIHTMLContent** aContent);
 
+  void AppendToCorrectParent(nsHTMLTag aParentTag,
+                             nsIHTMLContent* aParent,
+                             nsHTMLTag aChildTag,
+                             nsIHTMLContent* aChild,
+                             PRBool aAllowReflow);
+
   void GetAttributeValueAt(const nsIParserNode& aNode,
                            PRInt32 aIndex,
                            nsString& aResult);
@@ -731,7 +738,9 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode)
       }
 #endif
       
-      parent->AppendChild(container,  allowReflow);
+      AppendToCorrectParent(parentType, parent,
+                            (nsHTMLTag) aNode.GetNodeType(), container,
+                            allowReflow);
 #ifdef NS_DEBUG
       if (allowReflow && (((PRInt32)gSinkLogModuleInfo->level) > 127)) {
         PRInt32 i, ns = mDocument->GetNumberOfShells();
@@ -1051,10 +1060,12 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
 #ifdef NS_DEBUG
         if (allowReflow) {
           SINK_TRACE(SINK_TRACE_REFLOW,
-                     ("HTMLContentSink::CloseContainer: reflow after append"));
+                     ("HTMLContentSink::AddLeaf: reflow after append"));
         }
 #endif
-        parent->AppendChild(leaf, allowReflow);
+        AppendToCorrectParent(parentType, parent,
+                              (nsHTMLTag) aNode.GetNodeType(), leaf,
+                              allowReflow);
       } else {
         // XXX drop stuff on the floor that doesn't have a container!
         // Bad parser!
@@ -1066,6 +1077,107 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
   return 0;
 }
 
+// Special handling code to push unexpected table content out of the
+// table and into the table's parent, just before the table. Because
+// the table is a container, it will not have been added to it's
+// parent yet so we can just append the inappropriate content.
+void
+HTMLContentSink::AppendToCorrectParent(nsHTMLTag aParentTag,
+                                       nsIHTMLContent* aParent,
+                                       nsHTMLTag aChildTag,
+                                       nsIHTMLContent* aChild,
+                                       PRBool aAllowReflow)
+{
+  nsIHTMLContent* realParent = aParent;
+
+  // These are the tags that are allowed in a table
+  static char tableTagSet[] = {
+    eHTMLTag_tbody, eHTMLTag_thead, eHTMLTag_tfoot,
+    eHTMLTag_tr, eHTMLTag_col, eHTMLTag_colgroup,
+    eHTMLTag_caption,/* XXX ok? */
+    0,
+  };
+
+  // These are the tags that are allowed in a tbody/thead/tfoot
+  static char tbodyTagSet[] = {
+    eHTMLTag_tr,
+    eHTMLTag_caption,/* XXX ok? */
+    0,
+  };
+
+  // These are the tags that are allowed in a colgroup
+  static char colgroupTagSet[] = {
+    eHTMLTag_col,
+    0,
+  };
+
+  // These are the tags that are allowed in a tr
+  static char trTagSet[] = {
+    eHTMLTag_td, eHTMLTag_th,
+    0,
+  };
+
+  switch (aParentTag) {
+  case eHTMLTag_table:
+    if (0 == strchr(tableTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_tbody:
+  case eHTMLTag_thead:
+  case eHTMLTag_tfoot:
+    if (0 == strchr(tbodyTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_col:
+    realParent = GetTableParent();
+    break;
+
+  case eHTMLTag_colgroup:
+    if (0 == strchr(colgroupTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  case eHTMLTag_tr:
+    if (0 == strchr(trTagSet, aChildTag)) {
+      realParent = GetTableParent();
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  realParent->AppendChild(aChild, aAllowReflow);
+}
+
+// Find the parent of the currently open table
+nsIHTMLContent*
+HTMLContentSink::GetTableParent()
+{
+  PRInt32 sp = mStackPos - 1;
+  while (sp >= 0) {
+    switch (mNodeStack[sp]) {
+    case eHTMLTag_table:
+    case eHTMLTag_tr:
+    case eHTMLTag_tbody:
+    case eHTMLTag_thead:
+    case eHTMLTag_tfoot:
+    case eHTMLTag_col:
+    case eHTMLTag_colgroup:
+      break;
+    default:
+      return mContainerStack[sp];
+    }
+    sp--;
+  }
+  return mBody;
+}
+
 nsresult
 HTMLContentSink::AddText(const nsString& aText, nsIHTMLContent** aContent)
 {