Fixed CSS validation issue (no handling for line continuation). Reported by Suffusion...
authorTim Starling <tstarling@users.mediawiki.org>
Mon, 8 Mar 2010 22:22:01 +0000 (22:22 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Mon, 8 Mar 2010 22:22:01 +0000 (22:22 +0000)
includes/Sanitizer.php
maintenance/parserTests.txt

index 8533990..fd51b92 100644 (file)
@@ -738,24 +738,48 @@ class Sanitizer {
         * @return Mixed
         */
        static function checkCss( $value ) {
-               $stripped = Sanitizer::decodeCharReferences( $value );
+               $value = Sanitizer::decodeCharReferences( $value );
 
                // Remove any comments; IE gets token splitting wrong
-               $stripped = StringUtils::delimiterReplace( '/*', '*/', ' ', $stripped );
-
-               $value = $stripped;
-
-               // ... and continue checks
-               $stripped = preg_replace( '!\\\\([0-9A-Fa-f]{1,6})[ \\n\\r\\t\\f]?!e',
-                       'codepointToUtf8(hexdec("$1"))', $stripped );
-               $stripped = str_replace( '\\', '', $stripped );
-               if( preg_match( '/(?:expression|tps*:\/\/|url\\s*\().*/is',
-                               $stripped ) ) {
-                       # haxx0r
+               $value = StringUtils::delimiterReplace( '/*', '*/', ' ', $value );
+
+               // Decode escape sequences and line continuation
+               // See the grammar in the CSS 2 spec, appendix D, Mozilla implements it accurately.
+               // IE 8 doesn't implement it at all, but there's no way to introduce url() into
+               // IE that doesn't hit Mozilla also.
+               static $decodeRegex;
+               if ( !$decodeRegex ) {
+                       $space = '[\\x20\\t\\r\\n\\f]';
+                       $nl = '(?:\\n|\\r\\n|\\r|\\f)';
+                       $backslash = '\\\\';
+                       $decodeRegex = "/ $backslash 
+                               (?:
+                                       ($nl) |  # 1. Line continuation
+                                       ([0-9A-Fa-f]{1,6})$space? |  # 2. character number
+                                       (.) # 3. backslash cancelling special meaning
+                               )/xu";
+               }
+               $decoded = preg_replace_callback( $decodeRegex, 
+                       array( __CLASS__, 'cssDecodeCallback' ), $value );
+               if ( preg_match( '!expression|https?://|url\s*\(!i', $decoded ) ) {
+                       // Not allowed
                        return false;
+               } else {
+                       // Allowed, return CSS with comments stripped
+                       return $value;
                }
+       }
 
-               return $value;
+       static function cssDecodeCallback( $matches ) {
+               if ( $matches[1] !== '' ) {
+                       return '';
+               } elseif ( $matches[2] !== '' ) {
+                       return codepointToUtf8( hexdec( $matches[2] ) );
+               } elseif ( $matches[3] !== '' ) {
+                       return $matches[3];
+               } else {
+                       throw new MWException( __METHOD__.': invalid match' );
+               }
        }
 
        /**
index 14ce80e..f46a191 100644 (file)
@@ -4438,6 +4438,23 @@ Table attribute safety
 
 !! end
 
+!! test
+CSS line continuation 1
+!! input
+<div style="background-image: u\&#10;rl(test.jpg);"></div>
+!! result
+<div></div>
+
+!! end
+
+!! test
+CSS line continuation 2
+!! input
+<div style="background-image: u\&#13;rl(test.jpg); "></div>
+!! result
+<div></div>
+
+!! end
 
 !! article
 Template:Identity