diff -ur modules/filter/filter.module modules/filter/filter.module
--- modules/filter/filter.module	2009-03-15 02:53:16.000000000 +0100
+++ modules/filter/filter.module	2009-03-26 09:17:55.000000000 +0100
@@ -765,14 +765,14 @@
     $no_nesting = drupal_map_assoc(array('li', 'p'));
 
     // Single use tags in HTML4
-    $single_use = drupal_map_assoc(array('base', 'meta', 'link', 'hr', 'br', 'param', 'img', 'area', 'input', 'col', 'frame'));
+    $single_use = drupal_map_assoc(array('base', 'meta', 'link', 'hr', 'br', 'param', 'img', 'area', 'input', 'col', 'frame', '!--'));
   }
 
   // Properly entify angles.
-  $text = preg_replace('!<([^a-zA-Z/])!', '&lt;\1', $text);
+  $text = preg_replace('@<([^a-zA-Z/!])@', '&lt;\1', $text);
 
   // Split tags from text.
-  $split = preg_split('/<([^>]+?)>/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+  $split = preg_split('/<(!--.*?--|[^>]+?)>/s', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
   // Note: PHP ensures the array consists of alternating delimiters and literals
   // and begins and ends with a literal (inserting $null as required).
 
@@ -782,7 +782,7 @@
   foreach ($split as $value) {
     // Process HTML tags.
     if ($tag) {
-      list($tagname) = explode(' ', strtolower($value), 2);
+      list($tagname) = preg_split('/\s/', strtolower($value), 2);
       // Closing tag
       if ($tagname{0} == '/') {
         $tagname = substr($tagname, 1);
@@ -809,7 +809,7 @@
           array_unshift($stack, $tagname);
         }
         // Add trailing slash to single-use tags as per X(HT)ML.
-        else {
+        elseif ($tagname !== '!--') {
           $value = rtrim($value, ' /') . ' /';
         }
         $output .= '<' . $value . '>';
@@ -889,7 +889,7 @@
   // We don't apply any processing to the contents of these tags to avoid messing
   // up code. We look for matched pairs and allow basic nesting. For example:
   // "processed <pre> ignored <script> ignored </script> ignored </pre> processed"
-  $chunks = preg_split('@(</?(?:pre|script|style|object)[^>]*>)@i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+  $chunks = preg_split('@(<(?:!--.*?--|/?(?:pre|script|style|object)[^>]*)>)@si', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
   // Note: PHP ensures the array consists of alternating delimiters and literals
   // and begins and ends with a literal (inserting NULL as required).
   $ignore = FALSE;
diff -ur modules/filter/filter.test modules/filter/filter.test
--- modules/filter/filter.test	2009-03-15 02:53:16.000000000 +0100
+++ modules/filter/filter.test	2009-03-26 09:15:30.000000000 +0100
@@ -240,4 +240,15 @@
   function testInternalFilter() {
     $this->assertEqual(_filter_internal('[internal:foo/bar] [internal:foo2/bar2]'), url('foo/bar') . ' ' . url('foo2/bar2'), t('The internal filter works'));
   }
+
+  /**
+   * Test that the HTML corrector doesn't change the contents of HTML comments.
+   */
+  function testHtmlCorrectorComments() {
+    $f = _filter_autop("<!-- aaa\nbbb\n\nccc -->");
+    $this->assertEqual($f, "<!-- aaa\nbbb\n\nccc -->", t('Line breaking -- do not change comments.'));
+
+    $f = _filter_htmlcorrector("<!--\n<p> <br> comment\n//-->");
+    $this->assertEqual($f, "<!--\n<p> <br> comment\n//-->", t('HTML corrector -- skipping comments.'));
+  }
 }
