summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2013-10-12 12:28:40 +0200
committerAleksander Machniak <alec@alec.pl>2013-10-12 12:28:40 +0200
commitd1abd8e339a1346b02ebbca5365cd824adf5f897 (patch)
treeeb35fd54930cbccaa6d392c1169240f913f25773
parentb5216621ba79599157ac868c7f9b935a54e39b57 (diff)
Fix infinite loop in rcube_utils::mod_css_styles() after recent changes in rcube_string_replacer
-rw-r--r--program/lib/Roundcube/rcube_string_replacer.php6
-rw-r--r--program/lib/Roundcube/rcube_utils.php18
2 files changed, 14 insertions, 10 deletions
diff --git a/program/lib/Roundcube/rcube_string_replacer.php b/program/lib/Roundcube/rcube_string_replacer.php
index 85ccc95ee..77b91d18b 100644
--- a/program/lib/Roundcube/rcube_string_replacer.php
+++ b/program/lib/Roundcube/rcube_string_replacer.php
@@ -24,7 +24,7 @@
*/
class rcube_string_replacer
{
- public static $pattern = '/##str_replacement\{([0-9]+)\}##/';
+ public static $pattern = '/##str_replacement_(\d+)##/';
public $mailto_pattern;
public $link_pattern;
public $linkref_index;
@@ -50,7 +50,7 @@ class rcube_string_replacer
."@$utf_domain" // domain-part
."(\?[$url1$url2]+)?" // e.g. ?subject=test...
.")/";
- $this->linkref_index = '/\[([^\]#]+)\](:?\s*##str_replacement\{(\d+)\}##)/';
+ $this->linkref_index = '/\[([^\]#]+)\](:?\s*##str_replacement_(\d+)##)/';
$this->linkref_pattern = '/\[([^\]#]+)\]/';
$this->options = $options;
@@ -74,7 +74,7 @@ class rcube_string_replacer
*/
public function get_replacement($i)
{
- return '##str_replacement{'.$i.'}##';
+ return '##str_replacement_' . $i . '##';
}
/**
diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php
index c1ad3823b..771602fa7 100644
--- a/program/lib/Roundcube/rcube_utils.php
+++ b/program/lib/Roundcube/rcube_utils.php
@@ -445,34 +445,38 @@ class rcube_utils
$source = self::xss_entity_decode($source);
$stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
$evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : '');
+
if (preg_match("/$evilexpr/i", $stripped)) {
return '/* evil! */';
}
+ $strict_url_regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims';
+
// cut out all contents between { and }
while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) {
$styles = substr($source, $pos+1, $pos2-($pos+1));
+ $length = strlen($styles);
// check every line of a style block...
if ($allow_remote) {
$a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
+
foreach ($a_styles as $line) {
$stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
// ... and only allow strict url() values
- $regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims';
- if (stripos($stripped, 'url(') && !preg_match($regexp, $line)) {
+ if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
$a_styles = array('/* evil! */');
break;
}
}
+
$styles = join(";\n", $a_styles);
}
- $key = $replacements->add($styles);
- $source = substr($source, 0, $pos+1)
- . $replacements->get_replacement($key)
- . substr($source, $pos2, strlen($source)-$pos2);
- $last_pos = $pos+2;
+ $key = $replacements->add($styles);
+ $repl = $replacements->get_replacement($key);
+ $source = substr_replace($source, $repl, $pos+1, $length);
+ $last_pos = $pos2 - ($length - strlen($repl));
}
// remove html comments and add #container to each tag selector.