smarty-php / smarty-php/smarty

Smarty 5 regression: Template function `{call}` variables leak into caller scope under `extends:`

Open
#1,196 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
2.3k
Forks
709
PR merge metrics
No merged PRs in 30d

Description

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)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the self-contained PHP reproduction and compare the plain-template path with the extends:parent.tpl|child.tpl path. Trace the inheritance rendering path alongside the fix referenced in #954; done means both cases preserve x=OUTER on Smarty 5 without regressing plain templates.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.