From 85e05458c67c80ec8b3ef902d68318d5d4b21635 Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Wed, 20 May 2015 05:48:45 +0200 Subject: [PATCH] - bugfix compiler could run into the pcre.backtrack_limit on larger comment or {php} tag sections (forum 25538) --- change_log.txt | 1 + lexer/smarty_internal_templatelexer.plex | 18 ++++++------- libs/Smarty.class.php | 2 +- .../smarty_internal_templatelexer.php | 26 +++++++++---------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/change_log.txt b/change_log.txt index 42a4648f..760e4f8a 100644 --- a/change_log.txt +++ b/change_log.txt @@ -2,6 +2,7 @@ 19.05.2015 - bugfix compiler did overwrite existing variable value when setting the nocache attribute https://github.com/smarty-php/smarty/issues/39 - bugfix output filter trimwhitespace could run into the pcre.backtrack_limit on large output (code.google issue 220) + - bugfix compiler could run into the pcre.backtrack_limit on larger comment or {php} tag sections (forum 25538) 18.05.2015 - improvement introduce shortcuts in lexer/parser rules for most frequent terms for higher diff --git a/lexer/smarty_internal_templatelexer.plex b/lexer/smarty_internal_templatelexer.plex index 10c274ef..c6e3d0a9 100644 --- a/lexer/smarty_internal_templatelexer.plex +++ b/lexer/smarty_internal_templatelexer.plex @@ -235,12 +235,12 @@ class Smarty_Internal_Templatelexer namespace = /([0-9]*[a-zA-Z_]\w*)?(\\[0-9]*[a-zA-Z_]\w*)+/ all = /[\S\s]+/ emptyjava = /\{\}/ - xmltag = /<\?xml\s+([\S\s]*?)\?>/ - php = /(<\?(?:php\s+|=)?)((('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*")|(\/\*[\S\s]*?\*\/)|[\S\s])*?)\?>/ - phpscript = /((('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*")|(\/\*[\S\s]*?\*\/)|[\S\s])*?)<\/script>/ - phptag = /(SMARTYldel\s*php\s*(.)*?SMARTYrdel([\S\s]*?)SMARTYldel\s*\/php\s*SMARTYrdel)|(SMARTYldel\s*[\/]?php\s*(.)*?SMARTYrdel)/ - asp = /<%((('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*")|(\/\*[\S\s]*?\*\/)|[\S\s])*?)%>/ - unmatched = /(<(\?(?:php\s+|=)?|(script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)|%))|\?>|%>/ + xmltag = /<[?]xml\s+([\S\s]*?)[?]>/ + php = #<[?](?:php(?=[\s=]))?((?:(?![?]>)[^/][^?'"/]*)(([/][*](?:(?![*][/])[\S\s][^*]*)*[*][/])|([/][/][^\n]*)|('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*"))*)*[?]># + asp = #<[%]((?:(?![%]>)[^/][^%'"/]*)(([/][*](?:(?![*][/])[\S\s][^*]*)*[*][/])|([/][/][^\n]*)|('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*"))*)*[%]># + phpscript = #((?:(?!)[^/][^<'"/]*)(([/][*](?:(?![*][/])[\S\s][^*]*)*[*][/])|([/][/][^\n]*)|('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*"))*)*# + phptag = #((SMARTYldel\s*php\s*(.)*?SMARTYrdel)((?:(?!(SMARTYldel\s*[/]php\s*SMARTYrdel))[^/\{][^SMARTYldelFIRST'"/]*)(([/][*](?:(?![*][/])[\S\s][^*]*)*[*][/])|([/][/][^\n]*)|('[^'\\]*(?:\\.[^'\\]*)*')|("[^"\\]*(?:\\.[^"\\]*)*"))*)*(SMARTYldel\s*[/]php\s*SMARTYrdel)?)|(SMARTYldel\s*[/]?php\s*SMARTYrdel)# + unmatched = /((<[?](?:php\s+|=)?)|(])|<[%]|[?][>]|[%][>])/ slash = /\// ldel = /SMARTYldel\s*/ rdel = /\s*SMARTYrdel/ @@ -250,7 +250,7 @@ class Smarty_Internal_Templatelexer integer = /\d+/ hex = /0[xX][0-9a-fA-F]+/ math = /\s*([*]{1,2}|[%\/^&]|[<>]{2})\s*/ - comment = /SMARTYldel\*([\S\s]*?)\*SMARTYrdel/ + comment = /SMARTYldel[*]((?:(?![*]SMARTYrdel)[\S\s][^*]*))*[*]SMARTYrdel/ incdec = /\+\+|\-\-/ unimath = /\s*(\+|\-)\s*/ openP = /\s*\(\s*/ @@ -272,7 +272,7 @@ class Smarty_Internal_Templatelexer singlequotestring = /'[^'\\]*(?:\\.[^'\\]*)*'/ backtick = /`/ vert = /\|/ - qmark = /\s*\?\s*/ + qmark = /\s*[?]\s*/ constant = /([_]+[A-Z0-9][0-9A-Z_]*|[A-Z][0-9A-Z_]*)(?![0-9A-Z_]*[a-z])/ attr = /\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\s*=\s*/ id = /[0-9]*[a-zA-Z_]\w*/ @@ -349,7 +349,7 @@ class Smarty_Internal_Templatelexer } text { $to = strlen($this->data); - preg_match("/{$this->ldel}|<\?|<%|\?>|%>|/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + preg_match("/{$this->ldel}|<[?]|<%|[?]>|%>|/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); if (isset($match[0][1])) { $to = $match[0][1]; } diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 9c4a0314..265044f2 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -111,7 +111,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.24-dev/7'; + const SMARTY_VERSION = '3.1.24-dev/8'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_templatelexer.php b/libs/sysplugins/smarty_internal_templatelexer.php index 6bbc6feb..904461ed 100644 --- a/libs/sysplugins/smarty_internal_templatelexer.php +++ b/libs/sysplugins/smarty_internal_templatelexer.php @@ -255,7 +255,7 @@ class Smarty_Internal_Templatelexer public function yylex1() { if (!isset($this->yy_global_pattern1)) { - $this->yy_global_pattern1 = "/\G(\\{\\})|\G(" . $this->ldel . "\\*([\S\s]*?)\\*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*literal\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*)|\G(\\s*" . $this->rdel . ")|\G(<\\?xml\\s+([\S\s]*?)\\?>)|\G(<%((('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(\/\\*[\S\s]*?\\*\/)|[\S\s])*?)%>)|\G((<\\?(?:php\\s+|=)?)((('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(\/\\*[\S\s]*?\\*\/)|[\S\s])*?)\\?>)|\G(((('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(\/\\*[\S\s]*?\\*\/)|[\S\s])*?)<\/script>)|\G((<(\\?(?:php\\s+|=)?|(script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*>)|%))|\\?>|%>)|\G([\S\s])/iS"; + $this->yy_global_pattern1 = "/\G(\\{\\})|\G(" . $this->ldel . "[*]((?:(?![*]" . $this->rdel . ")[\S\s][^*]*))*[*]" . $this->rdel . ")|\G(" . $this->ldel . "\\s*literal\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*)|\G(\\s*" . $this->rdel . ")|\G(<[?]xml\\s+([\S\s]*?)[?]>)|\G(<[%]((?:(?![%]>)[^\/][^%'\"\/]*)(([\/][*](?:(?![*][\/])[\S\s][^*]*)*[*][\/])|([\/][\/][^\n]*)|('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"))*)*[%]>)|\G(<[?](?:php(?=[\s=]))?((?:(?![?]>)[^\/][^?'\"\/]*)(([\/][*](?:(?![*][\/])[\S\s][^*]*)*[*][\/])|([\/][\/][^\n]*)|('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"))*)*[?]>)|\G(((?:(?!<\/script>)[^\/][^<'\"\/]*)(([\/][*](?:(?![*][\/])[\S\s][^*]*)*[*][\/])|([\/][\/][^\n]*)|('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"))*)*<\/script>)|\G(((<[?](?:php\\s+|=)?)|(])|<[%]|[?][>]|[%][>]))|\G([\S\s])/iS"; } if ($this->counter >= strlen($this->data)) { return false; // end of input @@ -354,7 +354,7 @@ class Smarty_Internal_Templatelexer $this->token = Smarty_Internal_Templateparser::TP_PHP; } - function yy_r1_15() + function yy_r1_16() { $this->phpType = 'php'; @@ -362,7 +362,7 @@ class Smarty_Internal_Templatelexer $this->token = Smarty_Internal_Templateparser::TP_PHP; } - function yy_r1_22() + function yy_r1_23() { $this->phpType = 'script'; @@ -370,7 +370,7 @@ class Smarty_Internal_Templatelexer $this->token = Smarty_Internal_Templateparser::TP_PHP; } - function yy_r1_28() + function yy_r1_30() { $this->phpType = 'unmatched'; @@ -378,11 +378,11 @@ class Smarty_Internal_Templatelexer $this->token = Smarty_Internal_Templateparser::TP_PHP; } - function yy_r1_32() + function yy_r1_34() { $to = strlen($this->data); - preg_match("/{$this->ldel}|<\?|<%|\?>|%>|/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + preg_match("/{$this->ldel}|<[?]|<%|[?]>|%>|/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); if (isset($match[0][1])) { $to = $match[0][1]; } @@ -393,7 +393,7 @@ class Smarty_Internal_Templatelexer public function yylex2() { if (!isset($this->yy_global_pattern2)) { - $this->yy_global_pattern2 = "/\G(" . $this->ldel . "\\s*(if|elseif|else if|while)\\s+)|\G(" . $this->ldel . "\\s*for\\s+)|\G(" . $this->ldel . "\\s*foreach(?![^\s]))|\G(" . $this->ldel . "\\s*setfilter\\s+)|\G((" . $this->ldel . "\\s*php\\s*(.)*?" . $this->rdel . "([\S\s]*?)" . $this->ldel . "\\s*\/php\\s*" . $this->rdel . ")|(" . $this->ldel . "\\s*[\/]?php\\s*(.)*?" . $this->rdel . "))|\G(" . $this->ldel . "\\s*[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\/(?:(?!block)[0-9]*[a-zA-Z_]\\w*)\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\\$[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\/)|\G(" . $this->ldel . "\\s*)/iS"; + $this->yy_global_pattern2 = "/\G(" . $this->ldel . "\\s*(if|elseif|else if|while)\\s+)|\G(" . $this->ldel . "\\s*for\\s+)|\G(" . $this->ldel . "\\s*foreach(?![^\s]))|\G(" . $this->ldel . "\\s*setfilter\\s+)|\G(((" . $this->ldel . "\\s*php\\s*(.)*?" . $this->rdel . ")((?:(?!(" . $this->ldel . "\\s*[\/]php\\s*" . $this->rdel . "))[^\/{][^" . preg_quote($this->smarty->left_delimiter[0]) . "'\"\/]*)(([\/][*](?:(?![*][\/])[\S\s][^*]*)*[*][\/])|([\/][\/][^\n]*)|('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"))*)*(" . $this->ldel . "\\s*[\/]php\\s*" . $this->rdel . ")?)|(" . $this->ldel . "\\s*[\/]?php\\s*" . $this->rdel . "))|\G(" . $this->ldel . "\\s*[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\/(?:(?!block)[0-9]*[a-zA-Z_]\\w*)\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\\$[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*" . $this->rdel . ")|\G(" . $this->ldel . "\\s*\/)|\G(" . $this->ldel . "\\s*)/iS"; } if ($this->counter >= strlen($this->data)) { return false; // end of input @@ -478,7 +478,7 @@ class Smarty_Internal_Templatelexer $this->taglineno = $this->line; } - function yy_r2_12() + function yy_r2_19() { $this->yypopstate(); @@ -486,7 +486,7 @@ class Smarty_Internal_Templatelexer $this->taglineno = $this->line; } - function yy_r2_14() + function yy_r2_21() { $this->yypopstate(); @@ -494,7 +494,7 @@ class Smarty_Internal_Templatelexer $this->taglineno = $this->line; } - function yy_r2_15() + function yy_r2_22() { $this->yypopstate(); @@ -502,7 +502,7 @@ class Smarty_Internal_Templatelexer $this->taglineno = $this->line; } - function yy_r2_17() + function yy_r2_24() { $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; @@ -510,7 +510,7 @@ class Smarty_Internal_Templatelexer $this->taglineno = $this->line; } - function yy_r2_18() + function yy_r2_25() { $this->token = Smarty_Internal_Templateparser::TP_LDEL; @@ -521,7 +521,7 @@ class Smarty_Internal_Templatelexer public function yylex3() { if (!isset($this->yy_global_pattern3)) { - $this->yy_global_pattern3 = "/\G(\\s*" . $this->rdel . ")|\G(\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$]smarty\\.block\\.(child|parent))|\G(\\$[0-9]*[a-zA-Z_]\\w*)|\G(\\$)|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*(([!=][=]{1,2})|([<][=>]?)|([>][=]?)|[&|]{2})\\s*)|\G(\\s+(eq|ne|neg|gt|ge|gte|lt|le|lte|mod|and|or|xor|(is\\s+(not\\s+)?(odd|even|div)\\s+by))\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G(!\\s*|not\\s+)|\G(\\((int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)\\)\\s*)|\G(\\s*\\(\\s*)|\G(\\s*\\))|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*->\\s*)|\G(\\s*=>\\s*)|\G(\\s*=\\s*)|\G(\\+\\+|--)|\G(\\s*(\\+|-)\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G(@)|\G(#)|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*=\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G(`)|\G(\\|)|\G(\\.)|\G(\\s*,\\s*)|\G(\\s*;\\s*)|\G(::)|\G(\\s*:\\s*)|\G(\\s*\\?\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G(" . $this->ldel . "\\s*)|\G([\S\s])/iS"; + $this->yy_global_pattern3 = "/\G(\\s*" . $this->rdel . ")|\G(\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$]smarty\\.block\\.(child|parent))|\G(\\$[0-9]*[a-zA-Z_]\\w*)|\G(\\$)|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*(([!=][=]{1,2})|([<][=>]?)|([>][=]?)|[&|]{2})\\s*)|\G(\\s+(eq|ne|neg|gt|ge|gte|lt|le|lte|mod|and|or|xor|(is\\s+(not\\s+)?(odd|even|div)\\s+by))\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G(!\\s*|not\\s+)|\G(\\((int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)\\)\\s*)|\G(\\s*\\(\\s*)|\G(\\s*\\))|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*->\\s*)|\G(\\s*=>\\s*)|\G(\\s*=\\s*)|\G(\\+\\+|--)|\G(\\s*(\\+|-)\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G(@)|\G(#)|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*=\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G(`)|\G(\\|)|\G(\\.)|\G(\\s*,\\s*)|\G(\\s*;\\s*)|\G(::)|\G(\\s*:\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G(" . $this->ldel . "\\s*)|\G([\S\s])/iS"; } if ($this->counter >= strlen($this->data)) { return false; // end of input