diff --git a/change_log.txt b/change_log.txt index 70762eda..f7566f43 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,10 @@ -===== 3.1.33 release ===== 12.09.2018 +===== 3.1.34-dev-1 ===== +18.09.2018 + - bugfix large plain text template sections without a Smarty tag > 700kB could + could fail in version 3.1.32 and 3.1.33 because PHP preg_match() restrictions + https://github.com/smarty-php/smarty/issues/488 + +===== 3.1.33 release ===== 12.09.2018 ===== 3.1.33-dev-12 ===== 03.09.2018 - bugfix {foreach} using new style property access like {$item@property} on diff --git a/lexer/smarty_internal_templatelexer.plex b/lexer/smarty_internal_templatelexer.plex index 64a39310..afe1da90 100644 --- a/lexer/smarty_internal_templatelexer.plex +++ b/lexer/smarty_internal_templatelexer.plex @@ -209,6 +209,20 @@ class Smarty_Internal_Templatelexer */ private $yy_global_pattern5 = null; + /** + * preg token pattern for text + * + * @var null + */ + private $yy_global_text = null; + + /** + * preg token pattern for literal + * + * @var null + */ + private $yy_global_literal = null; + /** * constructor * @@ -330,8 +344,6 @@ class Smarty_Internal_Templatelexer not = ~[!]\s*|not\s+~ typecast = ~[(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\s*~ double_quote = ~["]~ - text = ~(.*?)(?=((SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["']?\s*php\s*["']?\s*[>]|[?][>]|[%][>]SMARTYliteral))|[\s\S]+~ - literaltext = ~(.*?)(?=(SMARTYldel)SMARTYal[/]?literalSMARTYrdel)~ */ /*!lex2php %statename TEXT @@ -339,7 +351,8 @@ class Smarty_Internal_Templatelexer $this->token = Smarty_Internal_Templateparser::TP_TEXT; } comment { - preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + $to = $this->dataLength; + preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); if (isset($match[0][1])) { $to = $match[0][1] + strlen($match[0][0]); } else { @@ -369,8 +382,17 @@ class Smarty_Internal_Templatelexer phpstart { $this->compiler->getTagCompiler('private_php')->parsePhp($this); } - text { - $this->token = Smarty_Internal_Templateparser::TP_TEXT; + char { + if (!isset($this->yy_global_text)) { + $this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_text, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } */ /*!lex2php @@ -601,8 +623,19 @@ class Smarty_Internal_Templatelexer $this->yypopstate(); } } - literaltext { - $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + char { + if (!isset($this->yy_global_literal)) { + $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_literal, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; } */ /*!lex2php @@ -648,7 +681,12 @@ class Smarty_Internal_Templatelexer textdoublequoted { $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - */ + char { + $to = $this->dataLength; + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ } \ No newline at end of file diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index a8969926..7499016b 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -27,7 +27,7 @@ * @author Uwe Tews * @author Rodney Rehm * @package Smarty - * @version 3.1.33 + * @version 3.1.34-dev */ /** * set SMARTY_DIR to absolute path to Smarty library files. @@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.33'; + const SMARTY_VERSION = '3.1.34-dev-1'; /** * define variable scopes */ diff --git a/libs/sysplugins/smarty_internal_templatelexer.php b/libs/sysplugins/smarty_internal_templatelexer.php index c6c49ef5..78fda3b8 100644 --- a/libs/sysplugins/smarty_internal_templatelexer.php +++ b/libs/sysplugins/smarty_internal_templatelexer.php @@ -215,9 +215,23 @@ class Smarty_Internal_Templatelexer */ private $yy_global_pattern5 = null; - private $_yy_state = 1; + /** + * preg token pattern for text + * + * @var null + */ + private $yy_global_text = null; - private $_yy_stack = array(); + /** + * preg token pattern for literal + * + * @var null + */ + private $yy_global_literal = null; + + private $_yy_state = 1; + + private $_yy_stack = array(); /** * constructor @@ -319,7 +333,7 @@ class Smarty_Internal_Templatelexer { if (!isset($this->yy_global_pattern1)) { $this->yy_global_pattern1 = - $this->replace("/\G([{][}])|\G((SMARTYldel)SMARTYal[*])|\G((SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[\/]phpSMARTYrdel)|\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([<][?]((php\\s+|=)|\\s+)|[<][%]|[<][?]xml\\s+|[<]script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*[>]|[?][>]|[%][>])|\G((.*?)(?=((SMARTYldel)SMARTYal|[<][?]((php\\s+|=)|\\s+)|[<][%]|[<][?]xml\\s+|[<]script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*[>]|[?][>]|[%][>]SMARTYliteral))|[\s\S]+)/isS"); + $this->replace("/\G([{][}])|\G((SMARTYldel)SMARTYal[*])|\G((SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[\/]phpSMARTYrdel)|\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([<][?]((php\\s+|=)|\\s+)|[<][%]|[<][?]xml\\s+|[<]script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*[>]|[?][>]|[%][>])|\G([\S\s])/isS"); } if (!isset($this->dataLength)) { $this->dataLength = strlen($this->data); @@ -336,11 +350,8 @@ class Smarty_Internal_Templatelexer } if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - ' an empty string. Input "' . substr( - $this->data, - $this->counter, - 5 - ) . '... state TEXT'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TEXT'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number @@ -379,6 +390,7 @@ class Smarty_Internal_Templatelexer public function yy_r1_2() { + $to = $this->dataLength; preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); if (isset($match[ 0 ][ 1 ])) { @@ -425,6 +437,16 @@ class Smarty_Internal_Templatelexer public function yy_r1_19() { + if (!isset($this->yy_global_text)) { + $this->yy_global_text = + $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_text, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ]; + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); $this->token = Smarty_Internal_Templateparser::TP_TEXT; } @@ -449,11 +471,8 @@ class Smarty_Internal_Templatelexer } if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - ' an empty string. Input "' . substr( - $this->data, - $this->counter, - 5 - ) . '... state TAG'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TAG'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number @@ -590,11 +609,8 @@ class Smarty_Internal_Templatelexer } if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - ' an empty string. Input "' . substr( - $this->data, - $this->counter, - 5 - ) . '... state TAGBODY'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TAGBODY'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number @@ -863,7 +879,7 @@ class Smarty_Internal_Templatelexer { if (!isset($this->yy_global_pattern4)) { $this->yy_global_pattern4 = - $this->replace("/\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((.*?)(?=(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel))/isS"); + $this->replace("/\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G([\S\s])/isS"); } if (!isset($this->dataLength)) { $this->dataLength = strlen($this->data); @@ -880,11 +896,8 @@ class Smarty_Internal_Templatelexer } if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - ' an empty string. Input "' . substr( - $this->data, - $this->counter, - 5 - ) . '... state LITERAL'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state LITERAL'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number @@ -935,6 +948,17 @@ class Smarty_Internal_Templatelexer public function yy_r4_5() { + if (!isset($this->yy_global_literal)) { + $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_literal, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ]; + } else { + $this->compiler->trigger_template_error("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); $this->token = Smarty_Internal_Templateparser::TP_LITERAL; } // end function @@ -942,7 +966,7 @@ class Smarty_Internal_Templatelexer { if (!isset($this->yy_global_pattern5)) { $this->yy_global_pattern5 = - $this->replace("/\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=((SMARTYldel)SMARTYal|\\$|`\\$|\"SMARTYliteral)))/isS"); + $this->replace("/\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=((SMARTYldel)SMARTYal|\\$|`\\$|\"SMARTYliteral)))|\G([\S\s])/isS"); } if (!isset($this->dataLength)) { $this->dataLength = strlen($this->data); @@ -959,11 +983,8 @@ class Smarty_Internal_Templatelexer } if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - ' an empty string. Input "' . substr( - $this->data, - $this->counter, - 5 - ) . '... state DOUBLEQUOTEDSTRING'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state DOUBLEQUOTEDSTRING'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number @@ -1057,4 +1078,13 @@ class Smarty_Internal_Templatelexer { $this->token = Smarty_Internal_Templateparser::TP_TEXT; } + + public function yy_r5_22() + { + $to = $this->dataLength; + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } } + + \ No newline at end of file