Fix infinite loop in rcube_utils::mod_css_styles() after recent changes in rcube_string_replacer

pull/136/head
Aleksander Machniak 11 years ago
parent b5216621ba
commit d1abd8e339

@ -24,7 +24,7 @@
*/ */
class rcube_string_replacer class rcube_string_replacer
{ {
public static $pattern = '/##str_replacement\{([0-9]+)\}##/'; public static $pattern = '/##str_replacement_(\d+)##/';
public $mailto_pattern; public $mailto_pattern;
public $link_pattern; public $link_pattern;
public $linkref_index; public $linkref_index;
@ -50,7 +50,7 @@ class rcube_string_replacer
."@$utf_domain" // domain-part ."@$utf_domain" // domain-part
."(\?[$url1$url2]+)?" // e.g. ?subject=test... ."(\?[$url1$url2]+)?" // e.g. ?subject=test...
.")/"; .")/";
$this->linkref_index = '/\[([^\]#]+)\](:?\s*##str_replacement\{(\d+)\}##)/'; $this->linkref_index = '/\[([^\]#]+)\](:?\s*##str_replacement_(\d+)##)/';
$this->linkref_pattern = '/\[([^\]#]+)\]/'; $this->linkref_pattern = '/\[([^\]#]+)\]/';
$this->options = $options; $this->options = $options;
@ -74,7 +74,7 @@ class rcube_string_replacer
*/ */
public function get_replacement($i) public function get_replacement($i)
{ {
return '##str_replacement{'.$i.'}##'; return '##str_replacement_' . $i . '##';
} }
/** /**

@ -445,34 +445,38 @@ class rcube_utils
$source = self::xss_entity_decode($source); $source = self::xss_entity_decode($source);
$stripped = preg_replace('/[^a-z\(:;]/i', '', $source); $stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
$evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : ''); $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : '');
if (preg_match("/$evilexpr/i", $stripped)) { if (preg_match("/$evilexpr/i", $stripped)) {
return '/* evil! */'; return '/* evil! */';
} }
$strict_url_regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims';
// cut out all contents between { and } // cut out all contents between { and }
while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) {
$styles = substr($source, $pos+1, $pos2-($pos+1)); $styles = substr($source, $pos+1, $pos2-($pos+1));
$length = strlen($styles);
// check every line of a style block... // check every line of a style block...
if ($allow_remote) { if ($allow_remote) {
$a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY); $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
foreach ($a_styles as $line) { foreach ($a_styles as $line) {
$stripped = preg_replace('/[^a-z\(:;]/i', '', $line); $stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
// ... and only allow strict url() values // ... and only allow strict url() values
$regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims'; if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
if (stripos($stripped, 'url(') && !preg_match($regexp, $line)) {
$a_styles = array('/* evil! */'); $a_styles = array('/* evil! */');
break; break;
} }
} }
$styles = join(";\n", $a_styles); $styles = join(";\n", $a_styles);
} }
$key = $replacements->add($styles); $key = $replacements->add($styles);
$source = substr($source, 0, $pos+1) $repl = $replacements->get_replacement($key);
. $replacements->get_replacement($key) $source = substr_replace($source, $repl, $pos+1, $length);
. substr($source, $pos2, strlen($source)-$pos2); $last_pos = $pos2 - ($length - strlen($repl));
$last_pos = $pos+2;
} }
// remove html comments and add #container to each tag selector. // remove html comments and add #container to each tag selector.

Loading…
Cancel
Save