- 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
This commit is contained in:
uwetews
2018-09-18 04:46:30 +02:00
parent dd55b23121
commit a6cb648dfc
4 changed files with 115 additions and 41 deletions

View File

@@ -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 ===== ===== 3.1.33-dev-12 =====
03.09.2018 03.09.2018
- bugfix {foreach} using new style property access like {$item@property} on - bugfix {foreach} using new style property access like {$item@property} on

View File

@@ -209,6 +209,20 @@ class Smarty_Internal_Templatelexer
*/ */
private $yy_global_pattern5 = null; 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 * constructor
* *
@@ -330,8 +344,6 @@ class Smarty_Internal_Templatelexer
not = ~[!]\s*|not\s+~ not = ~[!]\s*|not\s+~
typecast = ~[(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\s*~ typecast = ~[(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\s*~
double_quote = ~["]~ 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 /*!lex2php
%statename TEXT %statename TEXT
@@ -339,6 +351,7 @@ class Smarty_Internal_Templatelexer
$this->token = Smarty_Internal_Templateparser::TP_TEXT; $this->token = Smarty_Internal_Templateparser::TP_TEXT;
} }
comment { comment {
$to = $this->dataLength;
preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
if (isset($match[0][1])) { if (isset($match[0][1])) {
$to = $match[0][1] + strlen($match[0][0]); $to = $match[0][1] + strlen($match[0][0]);
@@ -369,7 +382,16 @@ class Smarty_Internal_Templatelexer
phpstart { phpstart {
$this->compiler->getTagCompiler('private_php')->parsePhp($this); $this->compiler->getTagCompiler('private_php')->parsePhp($this);
} }
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; $this->token = Smarty_Internal_Templateparser::TP_TEXT;
} }
*/ */
@@ -601,7 +623,18 @@ class Smarty_Internal_Templatelexer
$this->yypopstate(); $this->yypopstate();
} }
} }
literaltext { 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; $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
} }
*/ */
@@ -648,6 +681,11 @@ class Smarty_Internal_Templatelexer
textdoublequoted { textdoublequoted {
$this->token = Smarty_Internal_Templateparser::TP_TEXT; $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;
}
*/ */
} }

View File

@@ -27,7 +27,7 @@
* @author Uwe Tews <uwe dot tews at gmail dot com> * @author Uwe Tews <uwe dot tews at gmail dot com>
* @author Rodney Rehm * @author Rodney Rehm
* @package Smarty * @package Smarty
* @version 3.1.33 * @version 3.1.34-dev
*/ */
/** /**
* set SMARTY_DIR to absolute path to Smarty library files. * set SMARTY_DIR to absolute path to Smarty library files.
@@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '3.1.33'; const SMARTY_VERSION = '3.1.34-dev-1';
/** /**
* define variable scopes * define variable scopes
*/ */

View File

@@ -215,6 +215,20 @@ class Smarty_Internal_Templatelexer
*/ */
private $yy_global_pattern5 = null; 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;
private $_yy_state = 1; private $_yy_state = 1;
private $_yy_stack = array(); private $_yy_stack = array();
@@ -319,7 +333,7 @@ class Smarty_Internal_Templatelexer
{ {
if (!isset($this->yy_global_pattern1)) { if (!isset($this->yy_global_pattern1)) {
$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)) { if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data); $this->dataLength = strlen($this->data);
@@ -336,11 +350,8 @@ class Smarty_Internal_Templatelexer
} }
if (empty($yymatches)) { if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr( ' an empty string. Input "' . substr($this->data,
$this->data, $this->counter, 5) . '... state TEXT');
$this->counter,
5
) . '... state TEXT');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
@@ -379,6 +390,7 @@ class Smarty_Internal_Templatelexer
public function yy_r1_2() public function yy_r1_2()
{ {
$to = $this->dataLength;
preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/", $this->data, $match, PREG_OFFSET_CAPTURE, preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/", $this->data, $match, PREG_OFFSET_CAPTURE,
$this->counter); $this->counter);
if (isset($match[ 0 ][ 1 ])) { if (isset($match[ 0 ][ 1 ])) {
@@ -425,6 +437,16 @@ class Smarty_Internal_Templatelexer
public function yy_r1_19() 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; $this->token = Smarty_Internal_Templateparser::TP_TEXT;
} }
@@ -449,11 +471,8 @@ class Smarty_Internal_Templatelexer
} }
if (empty($yymatches)) { if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr( ' an empty string. Input "' . substr($this->data,
$this->data, $this->counter, 5) . '... state TAG');
$this->counter,
5
) . '... state TAG');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
@@ -590,11 +609,8 @@ class Smarty_Internal_Templatelexer
} }
if (empty($yymatches)) { if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr( ' an empty string. Input "' . substr($this->data,
$this->data, $this->counter, 5) . '... state TAGBODY');
$this->counter,
5
) . '... state TAGBODY');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
@@ -863,7 +879,7 @@ class Smarty_Internal_Templatelexer
{ {
if (!isset($this->yy_global_pattern4)) { if (!isset($this->yy_global_pattern4)) {
$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)) { if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data); $this->dataLength = strlen($this->data);
@@ -880,11 +896,8 @@ class Smarty_Internal_Templatelexer
} }
if (empty($yymatches)) { if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr( ' an empty string. Input "' . substr($this->data,
$this->data, $this->counter, 5) . '... state LITERAL');
$this->counter,
5
) . '... state LITERAL');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
@@ -935,6 +948,17 @@ class Smarty_Internal_Templatelexer
public function yy_r4_5() 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; $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
} // end function } // end function
@@ -942,7 +966,7 @@ class Smarty_Internal_Templatelexer
{ {
if (!isset($this->yy_global_pattern5)) { if (!isset($this->yy_global_pattern5)) {
$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)) { if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data); $this->dataLength = strlen($this->data);
@@ -959,11 +983,8 @@ class Smarty_Internal_Templatelexer
} }
if (empty($yymatches)) { if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr( ' an empty string. Input "' . substr($this->data,
$this->data, $this->counter, 5) . '... state DOUBLEQUOTEDSTRING');
$this->counter,
5
) . '... state DOUBLEQUOTEDSTRING');
} }
next($yymatches); // skip global match next($yymatches); // skip global match
$this->token = key($yymatches); // token number $this->token = key($yymatches); // token number
@@ -1057,4 +1078,13 @@ class Smarty_Internal_Templatelexer
{ {
$this->token = Smarty_Internal_Templateparser::TP_TEXT; $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;
} }
}