From a5b465e2c67b68e2d3ef51feaa22cbdabeed4642 Mon Sep 17 00:00:00 2001 From: uwetews Date: Thu, 25 Feb 2016 23:36:53 +0100 Subject: [PATCH] - optimization of _realpath --- change_log.txt | 1 + libs/Smarty.class.php | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/change_log.txt b/change_log.txt index 5e04cb45..8b70d731 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,6 +1,7 @@  ===== 3.1.30-dev ===== (xx.xx.xx) 25.02.2016 - bugfix wrong _realpath with 4 or more parent-directories https://github.com/smarty-php/smarty/issues/190 + - optimization of _realpath 20.02.2016 - bugfix {strip} must keep space between hmtl tags. Broken by changes of 10.2.2016 https://github.com/smarty-php/smarty/issues/184 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 04d6a451..22327fde 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.30-dev/48'; + const SMARTY_VERSION = '3.1.30-dev/49'; /** * define variable scopes @@ -1140,14 +1140,9 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function _realpath($path, $realpath = null) { - static $nds; - if ($nds == null) { - $nds = DS == '/' ? '\\' : '/'; - } + $nds = DS == '/' ? '\\' : '/'; // normalize DS - if (strpos($path, $nds) !== false) { - $path = str_replace($nds, DS, $path); - } + $path = str_replace($nds, DS, $path); preg_match('%^(?(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(?:[[:print:]]*))$%', $path, $parts); $path = $parts[ 'path' ]; @@ -1158,17 +1153,22 @@ class Smarty extends Smarty_Internal_TemplateBase $path = getcwd() . DS . $path; } } - $count = 1; - if (strpos($path, '..' . DS) != false) { - preg_match('#(([.]?[\\\\/])*([.][.])[\\\\/]([.]?[\\\\/])*)+#', $path, $match); - if (!$count = substr_count($match[ 0 ], '..')) { - $count = 1; + // remove noop 'DS DS' and 'DS.DS' patterns + $path = preg_replace('#([\\\\/]([.]?[\\\\/])+)#', DS, $path); + // resolve '..DS' pattern, smallest first + if (strpos($path, '..' . DS) != false && + preg_match_all('#(([.]?[\\\\/])*([.][.])[\\\\/]([.]?[\\\\/])*)+#', $path, $match) + ) { + $counts = array(); + foreach ($match[ 0 ] as $m) { + $counts[] = (int) ((strlen($m) - 1) / 3); + } + sort($counts); + foreach ($counts as $count) { + $path = preg_replace('#(([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count . + '}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . '})(?=[^.])#', + DS, $path); } - } - while ($count && ((strpos($path, '.' . DS) != false) || (strpos($path, DS . DS) != false))) { - $path = preg_replace('#([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count . - '}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . - '}|([\\\\/]([.]?[\\\\/])+)#', DS, $path, - 1, $count); } return $parts[ 'root' ] . $path;