From 08633bd182b49c035dc0a1727c52921402bcc1ec Mon Sep 17 00:00:00 2001 From: Ori Livneh Date: Mon, 1 Jun 2015 20:49:16 -0700 Subject: [PATCH] Use a fixed comment placeholder string in CSSMin Both the problem and solution are nearly identical to the ones presented in I31d4556bb. Use a constant string as a comment placeholder, and differentiate it from possible user input using \x7f, which is not valid CSS anyway[1]. [1]: http://www.w3.org/TR/CSS21/grammar.html Change-Id: I3d3c2578d5e9c1fe52c02e87901cb08d03847ea7 --- includes/libs/CSSMin.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/includes/libs/CSSMin.php b/includes/libs/CSSMin.php index ffe26a96c1..f415c9b6e7 100644 --- a/includes/libs/CSSMin.php +++ b/includes/libs/CSSMin.php @@ -31,6 +31,9 @@ class CSSMin { /* Constants */ + /** @var string Strip marker for comments. **/ + const PLACEHOLDER = "\x7fPLACEHOLDER\x7f"; + /** * Internet Explorer data URI length limit. See encodeImageAsDataURI(). */ @@ -232,19 +235,22 @@ class CSSMin { $remote = substr( $remote, 0, -1 ); } + // Disallow U+007F DELETE, which is illegal anyway, and which + // we use for comment placeholders. + $source = str_replace( "\x7f", "?", $source ); + // Replace all comments by a placeholder so they will not interfere with the remapping. // Warning: This will also catch on anything looking like the start of a comment between // quotation marks (e.g. "foo /* bar"). $comments = array(); - $placeholder = uniqid( '', true ); $pattern = '/(?!' . CSSMin::EMBED_REGEX . ')(' . CSSMin::COMMENT_REGEX . ')/s'; $source = preg_replace_callback( $pattern, - function ( $match ) use ( &$comments, $placeholder ) { + function ( $match ) use ( &$comments ) { $comments[] = $match[ 0 ]; - return $placeholder . ( count( $comments ) - 1 ) . 'x'; + return CSSMin::PLACEHOLDER . ( count( $comments ) - 1 ) . 'x'; }, $source ); @@ -257,13 +263,13 @@ class CSSMin { $source = preg_replace_callback( $pattern, - function ( $matchOuter ) use ( $local, $remote, $embedData, $placeholder ) { + function ( $matchOuter ) use ( $local, $remote, $embedData ) { $rule = $matchOuter[0]; // Check for global @embed comment and remove it. Allow other comments to be present // before @embed (they have been replaced with placeholders at this point). $embedAll = false; - $rule = preg_replace( '/^((?:\s+|' . $placeholder . '(\d+)x)*)' . CSSMin::EMBED_REGEX . '\s*/', '$1', $rule, 1, $embedAll ); + $rule = preg_replace( '/^((?:\s+|' . CSSMin::PLACEHOLDER . '(\d+)x)*)' . CSSMin::EMBED_REGEX . '\s*/', '$1', $rule, 1, $embedAll ); // Build two versions of current rule: with remapped URLs // and with embedded data: URIs (where possible). @@ -328,7 +334,7 @@ class CSSMin { }, $source ); // Re-insert comments - $pattern = '/' . $placeholder . '(\d+)x/'; + $pattern = '/' . CSSMin::PLACEHOLDER . '(\d+)x/'; $source = preg_replace_callback( $pattern, function( $match ) use ( &$comments ) { return $comments[ $match[1] ]; }, $source ); -- 2.20.1