From 93909aacf8df28cbd41b26adfc1a3af1de29ab9b Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Wed, 22 Nov 2017 01:21:09 +0100 Subject: [PATCH] bugfix {break} and {continue} could fail if {foreach}{/foreach} did contain other looping tags like {for}, {section} and {while} https://github.com/smarty-php/smarty/issues/323 --- change_log.txt | 4 +++ libs/Smarty.class.php | 2 +- .../smarty_internal_compile_break.php | 25 ++++++++++++------ .../smarty_internal_compile_continue.php | 26 ++++--------------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/change_log.txt b/change_log.txt index 4924f59b..81f6f0ef 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,8 @@ ===== 3.1.32 - dev === +22.11.2017 + - bugfix {break} and {continue} could fail if {foreach}{/foreach} did contain other + looping tags like {for}, {section} and {while} https://github.com/smarty-php/smarty/issues/323 + 20.11.2017 - bugfix rework of newline spacing between tag code and template text. now again identical with Smarty2 (forum topic 26878) diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 7d9aa9a1..3e84d0ec 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.32-dev-37'; + const SMARTY_VERSION = '3.1.32-dev-38'; /** * define variable scopes */ diff --git a/libs/sysplugins/smarty_internal_compile_break.php b/libs/sysplugins/smarty_internal_compile_break.php index 8879dff9..09c25d23 100644 --- a/libs/sysplugins/smarty_internal_compile_break.php +++ b/libs/sysplugins/smarty_internal_compile_break.php @@ -32,6 +32,13 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase */ public $shorttag_order = array('levels'); + /** + * Tag name may be overloaded by Smarty_Internal_Compile_Continue + * + * @var string + */ + public $tag = 'break'; + /** * Compiles code for the {break} tag * @@ -44,13 +51,16 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { list($levels, $foreachLevels) = $this->checkLevels($args, $compiler); - $output = " 0 && $this->tag === 'continue') { + $foreachLevels--; + } + if ($foreachLevels > 0) { /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */ $foreachCompiler = $compiler->getTagCompiler('foreach'); $output .= $foreachCompiler->compileRestore($foreachLevels); } - $output .= "break {$levels};?>"; + $output .= "{$this->tag} {$levels};?>"; return $output; } @@ -59,12 +69,11 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase * * @param array $args array with attributes from parser * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * @param string $tag tag name * * @return array * @throws \SmartyCompilerException */ - public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler, $tag = 'break') + public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler) { static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true); // check and get attributes @@ -86,7 +95,7 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase $stack_count = count($compiler->_tag_stack) - 1; $foreachLevels = 0; $lastTag = ''; - while ($level_count >= 0 && $stack_count >= 0) { + while ($level_count > 0 && $stack_count >= 0) { if (isset($_is_loopy[ $compiler->_tag_stack[ $stack_count ][ 0 ] ])) { $lastTag = $compiler->_tag_stack[ $stack_count ][ 0 ]; if ($level_count === 0) { @@ -100,9 +109,9 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase $stack_count --; } if ($level_count !== 0) { - $compiler->trigger_template_error("cannot {$tag} {$levels} level(s)", null, true); + $compiler->trigger_template_error("cannot {$this->tag} {$levels} level(s)", null, true); } - if ($lastTag === 'foreach' && $tag === 'break') { + if ($lastTag === 'foreach' && $this->tag === 'break' && $foreachLevels > 0) { $foreachLevels --; } return array($levels, $foreachLevels); diff --git a/libs/sysplugins/smarty_internal_compile_continue.php b/libs/sysplugins/smarty_internal_compile_continue.php index ac8efdc6..19e5d4be 100644 --- a/libs/sysplugins/smarty_internal_compile_continue.php +++ b/libs/sysplugins/smarty_internal_compile_continue.php @@ -17,25 +17,9 @@ class Smarty_Internal_Compile_Continue extends Smarty_Internal_Compile_Break { /** - * Compiles code for the {continue} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - * @throws \SmartyCompilerException - * @internal param array $parameter array with compilation parameter - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) - { - list($levels, $foreachLevels) = $this->checkLevels($args, $compiler, 'continue'); - $output = " 1) { - /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */ - $foreachCompiler = $compiler->getTagCompiler('foreach'); - $output .= $foreachCompiler->compileRestore($foreachLevels - 1); - } - $output .= "continue {$levels};?>"; - return $output; - } + * Tag name + * + * @var string + */ + public $tag = 'continue'; }