Variables assigned inside a {function} (both parameters and internal {assign}s) leak into the calling scope when the template is rendered through the extends: resource (template inheritance). The identical construct is correctly isolated in a plain template, and behaved correctly in Smarty 4.
This is the same symptom as #952 ("Function scoped variables overwriting parent scope"), which was fixed for plain templates by #954 - but that fix does not cover the inheritance path, so the leak still occurs there in 5.8.2.
Steps to reproduce
Self-contained script (writes its own templates):
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$dir = sys_get_temp_dir() . '/smrepro';
@mkdir($dir . '/templates', 0777, true);
@mkdir($dir . '/compiled', 0777, true);
array_map('unlink', glob($dir . '/compiled/*'));
// A template function that assigns a variable internally:
$fn = '{function name=test}{assign var="x" value="INNER"}{/function}' . "\n";
// Caller assigns its own $x, calls the function, then prints $x:
$logic = '{assign var="x" value="OUTER"}{test}x={$x}';
// Case A - plain template (no inheritance)
file_put_contents("$dir/templates/plain.tpl", $fn . $logic);
// Case B - same logic, but inside a {block} of a child that extends a parent
file_put_contents("$dir/templates/parent.tpl", '{block name=content}{/block}');
file_put_contents("$dir/templates/child.tpl", $fn . '{block name=content}' . $logic . '{/block}');
$smarty = new Smarty();
$smarty->setTemplateDir("$dir/templates")->setCompileDir("$dir/compiled");
$smarty->setForceCompile(true);
echo 'Smarty ' . Smarty::SMARTY_VERSION . "\n";
echo 'plain : ' . $smarty->fetch('plain.tpl') . " (expected: x=OUTER)\n";
echo 'extends: ' . $smarty->fetch('extends:parent.tpl|child.tpl') . " (expected: x=OUTER)\n";
Expected vs. actual
Expected: both print x=OUTER - the function's local assignment must not persist outside it.
| Smarty version |
plain template |
under extends: |
| 4.5.6 |
x=OUTER |
x=OUTER |
| 5.8.2 |
x=OUTER |
x=INNER (leak) |
Variables assigned inside a
{function}(both parameters and internal{assign}s) leak into the calling scope when the template is rendered through theextends:resource (template inheritance). The identical construct is correctly isolated in a plain template, and behaved correctly in Smarty 4.This is the same symptom as #952 ("Function scoped variables overwriting parent scope"), which was fixed for plain templates by #954 - but that fix does not cover the inheritance path, so the leak still occurs there in 5.8.2.
Steps to reproduce
Self-contained script (writes its own templates):
Expected vs. actual
Expected: both print
x=OUTER- the function's local assignment must not persist outside it.extends:x=OUTERx=OUTERx=OUTERx=INNER(leak)