Compare commits

..

46 Commits

Author SHA1 Message Date
Simon Wisselink 7eff7d6fb0 Changelog 2022-05-16 13:31:15 +02:00
Simon Wisselink 05f1a7deda Replace '*/' in user supplied input in C-style comments with '* /'. 2022-05-16 12:34:49 +02:00
Simon Wisselink 3f97b7352e Changelog 2022-04-26 22:11:59 +02:00
Simon Wisselink a6711b3833 Merge pull request #727 from liborm85/escape-modifier-fix
PHP 8.1: fix deprecation in escape modifier
2022-04-26 22:11:33 +02:00
Simon Wisselink 52056ce65a Changelog 2022-04-26 22:09:50 +02:00
Simon Wisselink 8b96efad45 Merge pull request #743 from xorti/fix-php81-rtrim-calls
Fix PHP 8.1 deprecated warning when calling rtrim
2022-04-26 22:09:10 +02:00
Simon Wisselink bfa02f3b91 Merge branch 'patch-1' 2022-04-26 22:06:29 +02:00
Simon Wisselink 89dc506638 Add changelog 2022-04-26 22:05:34 +02:00
Stephen Sigwart e68065bc33 Exclude demo from export and composer 2022-04-01 22:48:14 -04:00
Stephen Sigwart db2547287c Exclude docs from export and composer 2022-04-01 22:46:50 -04:00
Jorge Sá Pereira 962f266483 Fix PHP 8.1 deprecated warning when calling rtrim
Fixes - Deprecated: rtrim(): Passing null to parameter #1 ($string) of type string is deprecated
2022-03-10 02:06:00 +00:00
Simon Wisselink 8aeb5d6821 Merge pull request #726 from pH-7/patch-1
gitattributes: Ignore `.github` folder for distribution
2022-02-13 22:34:29 +01:00
Libor M a2e1df1768 PHP 8.1: fix deprecation in escape modifier 2022-02-08 13:30:19 +01:00
♚ PH⑦ de Soria™♛ fe6d333c60 Ignore .github folder for distribution
`.github` wasn't added here was it got created. However, we don't want `.github` for the distribution builds. Further info about this: https://www.pixelite.co.nz/article/using-git-attributes-exclude-files-your-release/
2022-02-08 06:32:27 +10:30
Simon Wisselink 50c4604857 Added issue 721 to changelog 2022-02-07 09:43:49 +01:00
Simon Wisselink e5a6ff42f8 Merge pull request #725 from smarty-php/bugfix/699
prevent float to int cast deprecation warning in truncate modifier
2022-02-06 22:25:34 +01:00
Simon Wisselink 3cc56392c6 prevent float to int cast deprecation warning in truncate modifier
Fixes #699
2022-02-06 22:20:05 +01:00
Simon Wisselink 17025423e1 Merge pull request #724 from smarty-php/bugfix/706
Fix PHP 8.1 deprecation notices in demo/plugins/cacheresource.pdo.php
2022-02-06 22:09:39 +01:00
Simon Wisselink 18d3e564da Merge branch 'master' into bugfix/706 2022-02-06 22:05:01 +01:00
Simon Wisselink 0d2c38b482 fix PHP 8.1 deprecation notices in demo/plugins/cacheresource.pdo.php
Fixes #706
2022-02-06 22:03:24 +01:00
Simon Wisselink f90348971b Merge pull request #722 from kochichi/bugfix/721
math equation return warning: max(x, y)
2022-02-06 21:54:54 +01:00
Simon Wisselink 9e0536de18 Merge branch 'release/4.1.0' 2022-02-06 21:34:27 +01:00
Simon Wisselink 265cf4f3bc version bump 2022-02-06 21:34:26 +01:00
Simon Wisselink 47f95ad324 Merge pull request #717 from vemaeg/php81-doc
Updating PHP 8.0 to 8.1 in the docs and add php8.1 test runner.
2022-02-06 21:30:52 +01:00
Pavel Kochman 02633ecaba math equation return warning: math: illegal character for : {math equation="max(x, y)" x=$x y=$y} 2022-02-04 21:03:25 +01:00
Thomas A. Hirsch 6786623afb Activating jit compiler for ubuntu-latest + php 8.1 2022-01-21 17:58:35 +01:00
Thomas 2d97169086 Merge branch 'smarty-php:master' into php81-doc 2022-01-21 17:57:27 +01:00
Thomas 0f098802c6 Create getting-started.md 2022-01-21 17:55:23 +01:00
Thomas bbcd5817f6 Update README.md 2022-01-21 17:51:45 +01:00
Simon Wisselink 612094d763 Updated changelog 2022-01-21 10:21:00 +01:00
Simon Wisselink 0ef0dda825 Merge pull request #713 from vemaeg/php81
PHP 8.1 compatibility (without IntlDateFormatter)
2022-01-21 10:18:48 +01:00
Thomas BACCELLI cef8951100 Add PHP 8.1 tests 2022-01-18 15:56:23 +01:00
Thomas BACCELLI 323aefa89f Fix phpunit warning 2022-01-18 15:56:23 +01:00
Thomas A. Hirsch 277648b81c Cherry-picked from da76d927ed
Co-Authored-By: Thomas BACCELLI <tbaccelli@gmail.com>
2022-01-18 15:56:23 +01:00
Thomas A. Hirsch 8d3a7af308 Cherry-picked from da76d927ed
Co-Authored-By: Thomas BACCELLI <tbaccelli@gmail.com>
2022-01-18 15:56:23 +01:00
Simon Wisselink cdf0f2b164 Merge branch 'release/4.0.4' 2022-01-18 00:17:19 +01:00
Simon Wisselink 995b7eb36f version bump 2022-01-18 00:17:17 +01:00
Claas Augner 059bea274c Support multiple operators in math equations (#708)
* fix(math): fix equation regexp

Fixes #702.
2022-01-18 00:10:17 +01:00
Simon Wisselink f707dadecb Merge branch 'release/4.0.3' 2022-01-10 10:52:14 +01:00
Simon Wisselink ace1c8e90f version bump 2022-01-10 10:52:13 +01:00
Simon Wisselink 19ae410bf5 Merge pull request from GHSA-4h9c-v5vg-5m6m
* Prevent evasion of the static_classes security policy.

* Updated deprecated exception expectations.
2022-01-10 10:48:27 +01:00
Simon Wisselink baad3115cd Fixed PHPUnit expected Exceptions. (#701) 2022-01-10 09:46:01 +01:00
Simon Wisselink 6f4f06db7e Merge branch 'release/4.0.2' 2022-01-10 00:09:08 +01:00
Simon Wisselink a535445dfd version bump 2022-01-10 00:09:06 +01:00
Simon Wisselink 215d81a9fa Merge pull request from GHSA-29gp-2c3m-3j6m
* Temporary fix. Waiting for CVE

* Add CVE
2022-01-10 00:01:43 +01:00
Simon Wisselink efb416e5ef Fixed unit tests 2022-01-09 23:29:43 +01:00
30 changed files with 224 additions and 66 deletions
+4 -1
View File
@@ -7,7 +7,10 @@
# exclude from git export
/tests export-ignore
/utilities/ export-ignore
/demo export-ignore
/docs export-ignore
/utilities export-ignore
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
+4
View File
@@ -28,6 +28,7 @@ jobs:
- "7.3"
- "7.4"
- "8.0"
- "8.1"
compiler:
- default
@@ -36,6 +37,9 @@ jobs:
- os: ubuntu-latest
php-version: "8.0"
compiler: jit
- os: ubuntu-latest
php-version: "8.1"
compiler: jit
steps:
- name: Checkout
+31
View File
@@ -6,6 +6,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Security
- Prevent PHP injection through malicious block name or include file name. This addresses CVE-2022-
### Fixed
- Exclude docs and demo from export and composer [#751](https://github.com/smarty-php/smarty/pull/751)
- PHP 8.1 deprecation notices in demo/plugins/cacheresource.pdo.php [#706](https://github.com/smarty-php/smarty/issues/706)
- PHP 8.1 deprecation notices in truncate modifier [#699](https://github.com/smarty-php/smarty/issues/699)
- Math equation `max(x, y)` didn't work anymore [#721](https://github.com/smarty-php/smarty/issues/721)
- Fix PHP 8.1 deprecated warning when calling rtrim [#743](https://github.com/smarty-php/smarty/pull/743)
- PHP 8.1: fix deprecation in escape modifier [#727](https://github.com/smarty-php/smarty/pull/727)
## [4.1.0] - 2022-02-06
### Added
- PHP8.1 compatibility [#713](https://github.com/smarty-php/smarty/pull/713)
## [4.0.4] - 2022-01-18
### Fixed
- Fixed illegal characters bug in math function security check [#702](https://github.com/smarty-php/smarty/issues/702)
## [4.0.3] - 2022-01-10
### Security
- Prevent evasion of the `static_classes` security policy. This addresses CVE-2021-21408
## [4.0.2] - 2022-01-10
### Security
- Prevent arbitrary PHP code execution through maliciously crafted expression for the math function. This addresses CVE-2021-29454
## [4.0.1] - 2022-01-09
### Security
+1 -1
View File
@@ -7,7 +7,7 @@ Smarty is a template engine for PHP, facilitating the separation of presentation
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
## Requirements
Smarty can be run with PHP 7.1 to PHP 8.0.
Smarty can be run with PHP 7.1 to PHP 8.1.
## Installation
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
+2 -2
View File
@@ -196,7 +196,7 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
* @return void
* @access protected
*/
protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime)
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
{
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
$stmt->execute();
@@ -244,7 +244,7 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
* @return boolean success
* @access protected
*/
protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content)
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
{
$stmt = $this->pdo->prepare($this->insertStatement);
$stmt->bindValue('id', $id);
+1 -1
View File
@@ -2,7 +2,7 @@ What is Smarty?
==============
## Requirements
Smarty can be run with PHP 7.1 to PHP 8.0.
Smarty can be run with PHP 7.1 to PHP 8.1.
## Installation
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
+3
View File
@@ -747,6 +747,9 @@ value(res) ::= doublequoted_with_quotes(s). {
value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
if ($this->security && $this->security->static_classes !== array()) {
$this->compiler->trigger_template_error('dynamic static class not allowed by security setting');
}
$prefixVar = $this->compiler->getNewPrefixVariable();
if (vi['var'] === '\'smarty\'') {
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>');
+4 -4
View File
@@ -98,7 +98,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '4.0.1';
const SMARTY_VERSION = '4.1.0';
/**
* define variable scopes
*/
@@ -867,7 +867,7 @@ class Smarty extends Smarty_Internal_TemplateBase
$this->plugins_dir = (array)$this->plugins_dir;
}
foreach ($this->plugins_dir as $k => $v) {
$this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, '/\\') . DIRECTORY_SEPARATOR, true);
$this->plugins_dir[ $k ] = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true);
}
$this->_cache[ 'plugin_files' ] = array();
$this->_pluginsDirNormalized = true;
@@ -1345,7 +1345,7 @@ class Smarty extends Smarty_Internal_TemplateBase
*/
private function _normalizeDir($dirName, $dir)
{
$this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . DIRECTORY_SEPARATOR, true);
$this->{$dirName} = $this->_realpath(rtrim($dir ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
}
/**
@@ -1367,7 +1367,7 @@ class Smarty extends Smarty_Internal_TemplateBase
}
foreach ($dir as $k => $v) {
if (!isset($processed[ $k ])) {
$dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true);
$dir[ $k ] = $v = $this->_realpath(rtrim($v ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
$processed[ $k ] = true;
}
}
+31 -1
View File
@@ -28,7 +28,12 @@ function smarty_function_math($params, $template)
'int' => true,
'abs' => true,
'ceil' => true,
'acos' => true,
'acosh' => true,
'cos' => true,
'cosh' => true,
'deg2rad' => true,
'rad2deg' => true,
'exp' => true,
'floor' => true,
'log' => true,
@@ -39,27 +44,51 @@ function smarty_function_math($params, $template)
'pow' => true,
'rand' => true,
'round' => true,
'asin' => true,
'asinh' => true,
'sin' => true,
'sinh' => true,
'sqrt' => true,
'srand' => true,
'tan' => true
'atan' => true,
'atanh' => true,
'tan' => true,
'tanh' => true
);
// be sure equation parameter is present
if (empty($params[ 'equation' ])) {
trigger_error("math: missing equation parameter", E_USER_WARNING);
return;
}
$equation = $params[ 'equation' ];
// Remove whitespaces
$equation = preg_replace('/\s+/', '', $equation);
// Adapted from https://www.php.net/manual/en/function.eval.php#107377
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';
$operators = '[,+\/*\^%-]'; // Allowed math operators
$regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*\((?1)+\)|\((?1)+\)))(?:'.$operators.'(?1))?)+$/';
if (!preg_match($regexp, $equation)) {
trigger_error("math: illegal characters", E_USER_WARNING);
return;
}
// make sure parenthesis are balanced
if (substr_count($equation, '(') !== substr_count($equation, ')')) {
trigger_error("math: unbalanced parenthesis", E_USER_WARNING);
return;
}
// disallow backticks
if (strpos($equation, '`') !== false) {
trigger_error("math: backtick character not allowed in equation", E_USER_WARNING);
return;
}
// also disallow dollar signs
if (strpos($equation, '$') !== false) {
trigger_error("math: dollar signs not allowed in equation", E_USER_WARNING);
@@ -96,6 +125,7 @@ function smarty_function_math($params, $template)
}
$smarty_math_result = null;
eval("\$smarty_math_result = " . $equation . ";");
if (empty($params[ 'format' ])) {
if (empty($params[ 'assign' ])) {
return $smarty_math_result;
+3
View File
@@ -29,6 +29,9 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
if (!$char_set) {
$char_set = Smarty::$_CHARSET;
}
$string = (string)$string;
switch ($esc_type) {
case 'html':
if ($_double_encode) {
+3 -3
View File
@@ -42,8 +42,8 @@ function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_wo
if (!$middle) {
return mb_substr($string, 0, $length, Smarty::$_CHARSET) . $etc;
}
return mb_substr($string, 0, $length / 2, Smarty::$_CHARSET) . $etc .
mb_substr($string, -$length / 2, $length, Smarty::$_CHARSET);
return mb_substr($string, 0, intval($length / 2), Smarty::$_CHARSET) . $etc .
mb_substr($string, -intval($length / 2), $length, Smarty::$_CHARSET);
}
return $string;
}
@@ -56,7 +56,7 @@ function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_wo
if (!$middle) {
return substr($string, 0, $length) . $etc;
}
return substr($string, 0, $length / 2) . $etc . substr($string, -$length / 2);
return substr($string, 0, intval($length / 2)) . $etc . substr($string, -intval($length / 2));
}
return $string;
}
+10 -10
View File
@@ -42,10 +42,10 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
switch ($esc_type) {
case 'html':
if ($_double_encode) {
return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
var_export($double_encode, true) . ')';
} elseif ($double_encode) {
return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
} else {
// fall back to modifier.escape.php
}
@@ -54,12 +54,12 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
if (Smarty::$_MBSTRING) {
if ($_double_encode) {
// php >=5.2.3 - go native
return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' .
var_export($char_set, true) . ', ' . var_export($double_encode, true) .
'), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
} elseif ($double_encode) {
// php <5.2.3 - only handle double encoding
return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' .
var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
} else {
// fall back to modifier.escape.php
@@ -68,26 +68,26 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
// no MBString fallback
if ($_double_encode) {
// php >=5.2.3 - go native
return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
var_export($double_encode, true) . ')';
} elseif ($double_encode) {
// php <5.2.3 - only handle double encoding
return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
} else {
// fall back to modifier.escape.php
}
// no break
case 'url':
return 'rawurlencode(' . $params[ 0 ] . ')';
return 'rawurlencode((string)' . $params[ 0 ] . ')';
case 'urlpathinfo':
return 'str_replace("%2F", "/", rawurlencode(' . $params[ 0 ] . '))';
return 'str_replace("%2F", "/", rawurlencode((string)' . $params[ 0 ] . '))';
case 'quotes':
// escape unescaped single quotes
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'",' . $params[ 0 ] . ')';
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'", (string)' . $params[ 0 ] . ')';
case 'javascript':
// escape quotes and backslashes, newlines, etc.
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
return 'strtr(' .
return 'strtr((string)' .
$params[ 0 ] .
', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/", "<!--" => "<\!--", "<s" => "<\s", "<S" => "<\S" ))';
}
@@ -196,8 +196,8 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/
public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
{
clearstatcache(true, $cached->lock_id);
if (is_file($cached->lock_id)) {
clearstatcache(true, $cached->lock_id ?? '');
if (null !== $cached->lock_id && is_file($cached->lock_id)) {
$t = filemtime($cached->lock_id);
return $t && (time() - $t < $smarty->locking_timeout);
} else {
@@ -125,7 +125,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_
// setup buffer for template function code
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
$output = "<?php\n";
$output .= "/* {block {$_name}} */\n";
$output .= $compiler->cStyleComment(" {block {$_name}} ") . "\n";
$output .= "class {$_className} extends Smarty_Internal_Block\n";
$output .= "{\n";
foreach ($_block as $property => $value) {
@@ -155,7 +155,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_
}
$output .= "}\n";
$output .= "}\n";
$output .= "/* {/block {$_name}} */\n\n";
$output .= $compiler->cStyleComment(" {/block {$_name}} ") . "\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree(
$compiler->parser,
@@ -134,7 +134,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
if ($compiler->template->compiled->has_nocache_code) {
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name_caching' ] = $_funcNameCaching;
$output = "<?php\n";
$output .= "/* {$_funcNameCaching} */\n";
$output .= $compiler->cStyleComment(" {$_funcNameCaching} ") . "\n";
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
$output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
$output .= "ob_start();\n";
@@ -157,9 +157,9 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
$output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n";
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>";
$output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash, ob_get_clean());\n";
$output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash ?? '', ob_get_clean());\n";
$output .= "}\n}\n";
$output .= "/*/ {$_funcName}_nocache */\n\n";
$output .= $compiler->cStyleComment("/ {$_funcName}_nocache ") . "\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree(
$compiler->parser,
@@ -179,7 +179,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
}
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name' ] = $_funcName;
$output = "<?php\n";
$output .= "/* {$_funcName} */\n";
$output .= $compiler->cStyleComment(" {$_funcName} ") . "\n";
$output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
$output .= $_paramsCode;
@@ -196,7 +196,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
);
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
$output = "<?php\n}}\n";
$output .= "/*/ {$_funcName} */\n\n";
$output .= $compiler->cStyleComment("/ {$_funcName} ") . "\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree(
$compiler->parser,
@@ -318,14 +318,14 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
// get compiled code
$compiled_code = "<?php\n\n";
$compiled_code .= "/* Start inline template \"{$sourceInfo}\" =============================*/\n";
$compiled_code .= $compiler->cStyleComment(" Start inline template \"{$sourceInfo}\" =============================") . "\n";
$compiled_code .= "function {$tpl->compiled->unifunc} (Smarty_Internal_Template \$_smarty_tpl) {\n";
$compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
$compiled_code .= "<?php\n";
$compiled_code .= "}\n?>\n";
$compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
$compiled_code .= "<?php\n\n";
$compiled_code .= "/* End inline template \"{$sourceInfo}\" =============================*/\n";
$compiled_code .= $compiler->cStyleComment(" End inline template \"{$sourceInfo}\" =============================") . "\n";
$compiled_code .= '?>';
unset($tpl->compiler);
if ($tpl->compiled->has_nocache_code) {
@@ -93,7 +93,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
}
if (!empty($_dir)) {
foreach ((array)$_dir as $_script_dir) {
$_script_dir = rtrim($_script_dir, '/\\') . DIRECTORY_SEPARATOR;
$_script_dir = rtrim($_script_dir ?? '', '/\\') . DIRECTORY_SEPARATOR;
if (file_exists($_script_dir . $_script)) {
$_filepath = $_script_dir . $_script;
break;
@@ -157,10 +157,12 @@ class Smarty_Internal_Config_File_Compiler
$this->smarty->_debug->end_compile($this->template);
}
// template header code
$template_header =
"<?php /* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S") .
"\n";
$template_header .= " compiled from '{$this->template->source->filepath}' */ ?>\n";
$template_header = sprintf(
"<?php /* Smarty version %s, created on %s\n compiled from '%s' */ ?>\n",
Smarty::SMARTY_VERSION,
date("Y-m-d H:i:s"),
str_replace('*/', '* /' , $this->template->source->filepath)
);
$code = '<?php $_smarty_tpl->smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' .
var_export($this->config_data, true) . '); ?>';
return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code);
@@ -44,9 +44,12 @@ class Smarty_Internal_Runtime_CodeFrame
$properties[ 'file_dependency' ] = $_template->cached->file_dependency;
$properties[ 'cache_lifetime' ] = $_template->cache_lifetime;
}
$output = "<?php\n";
$output .= "/* Smarty version {$properties[ 'version' ]}, created on " . strftime("%Y-%m-%d %H:%M:%S") .
"\n from '" . str_replace('*/', '* /', $_template->source->filepath) . "' */\n\n";
$output = sprintf(
"<?php\n/* Smarty version %s, created on %s\n from '%s' */\n\n",
$properties[ 'version' ],
date("Y-m-d H:i:s"),
str_replace('*/', '* /', $_template->source->filepath)
);
$output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n";
$dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' .
($cache ? 'true' : 'false') . ')';
@@ -1135,7 +1135,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
flush();
}
$e = new SmartyCompilerException($error_text);
$e->line = $line;
$e->setLine($line);
$e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ]));
$e->desc = $args;
$e->template = $this->template->source->filepath;
@@ -1439,6 +1439,10 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
abstract protected function doCompile($_content, $isTemplateSource = false);
public function cStyleComment($string) {
return '/*' . str_replace('*/', '* /' , $string) . '*/';
}
/**
* Compile Tag
*
@@ -2397,6 +2397,9 @@ public static $yy_action = array(
}
// line 749 "../smarty/lexer/smarty_internal_templateparser.y"
public function yy_r94(){
if ($this->security && $this->security->static_classes !== array()) {
$this->compiler->trigger_template_error('dynamic static class not allowed by security setting');
}
$prefixVar = $this->compiler->getNewPrefixVariable();
if ($this->yystack[$this->yyidx + -2]->minor['var'] === '\'smarty\'') {
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index']).';?>');
+5 -5
View File
@@ -16,12 +16,12 @@ class SmartyCompilerException extends SmartyException
}
/**
* The line number of the template error
*
* @type int|null
* @param int $line
*/
public $line = null;
public function setLine($line)
{
$this->line = $line;
}
/**
* The template source snippet relating to the error
*
@@ -30,7 +30,8 @@ class CacheResourceTestCommon extends PHPUnit_Smarty
public function compiledPrefilter($text, Smarty_Internal_Template $tpl)
{
return str_replace('#', $tpl->getTemplateVars('test'), $text);
$replace = $tpl->getTemplateVars('test');
return str_replace('#', $replace ?? '', $text);
}
/**
@@ -13,7 +13,7 @@ class Smarty_Resource_Ambiguous extends Smarty_Internal_Resource_File
public function __construct($directory)
{
$this->directory = rtrim($directory, "/\\") . DIRECTORY_SEPARATOR;
$this->directory = rtrim($directory ?? '', "/\\") . DIRECTORY_SEPARATOR;
// parent::__construct();
}
@@ -234,7 +234,7 @@ class ResourceStream
$v = &$GLOBALS[$this->varname];
$l = strlen($data);
$p = &$this->position;
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
return $l;
}
+31 -9
View File
@@ -257,19 +257,41 @@ class SecurityTest extends PHPUnit_Smarty
$this->assertEquals('25', $this->smarty->fetch($tpl));
}
/**
* test not trusted PHP function
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testNotTrustedStaticClass()
{
/**
* test not trusted PHP function
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testNotTrustedStaticClass()
{
$this->expectException('SmartyException');
$this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassEval()
{
$this->expectException('SmartyException');
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$test = "mysecuritystaticclass"}{$test::square(5)}');
}
/**
* test not trusted PHP function
*/
public function testNotTrustedStaticClassSmartyVar()
{
$this->expectException('SmartyException');
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
$this->smarty->security_policy->static_classes = array('null');
$this->smarty->fetch('string:{$smarty.template_object::square(5)}');
}
public function testChangedTrustedDirectory()
{
$this->smarty->security_policy->secure_dir = array(
@@ -344,9 +366,9 @@ class SecurityTest extends PHPUnit_Smarty
/**
* In security mode, accessing $smarty.template_object should be illegal.
* @expectedException SmartyCompilerException
*/
public function testSmartyTemplateObject() {
$this->expectException(SmartyCompilerException::class);
$this->smarty->display('string:{$smarty.template_object}');
}
@@ -394,7 +416,7 @@ class ResourceStreamSecurity
$v = &$GLOBALS[$this->varname];
$l = strlen($data);
$p = &$this->position;
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
return $l;
}
@@ -54,7 +54,7 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
public function testEncodeJavascript()
{
$result = '<script type="text/javascript">eval(unescape(\'%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%20%3e%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%3c%2f%61%3e%27%29%3b\'))</script>';
$result = '<script type="text/javascript">document.write(unescape(\'%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%20%3e%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%3c%2f%61%3e\'))</script>';
$tpl = $this->smarty->createTemplate('eval:{mailto address="me@example.com" encode="javascript"}');
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
}
@@ -62,7 +62,7 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
public function testEncodeJavascriptWithoutMbstring()
{
Smarty::$_MBSTRING = false;
$result = '<script type="text/javascript">eval(unescape(\'%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%20%3e%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%3c%2f%61%3e%27%29%3b\'))</script>';
$result = '<script type="text/javascript">document.write(unescape(\'%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%20%3e%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%3c%2f%61%3e\'))</script>';
$tpl = $this->smarty->createTemplate('eval:{mailto address="me@example.com" encode="javascript"}');
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
Smarty::$_MBSTRING = true;
@@ -70,7 +70,7 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
public function testEncodeJavascriptCharcode()
{
$result = "<script type=\"text/javascript\" language=\"javascript\">\n{document.write(String.fromCharCode(60,97,32,104,114,101,102,61,34,109,97,105,108,116,111,58,109,101,64,101,120,97,109,112,108,101,46,99,111,109,34,32,62,109,101,64,101,120,97,109,112,108,101,46,99,111,109,60,47,97,62))}\n</script>\n";
$result = '<script type="text/javascript">document.write(String.fromCharCode(60,97,32,104,114,101,102,61,34,109,97,105,108,116,111,58,109,101,64,101,120,97,109,112,108,101,46,99,111,109,34,32,62,109,101,64,101,120,97,109,112,108,101,46,99,111,109,60,47,97,62))</script>';
$tpl = $this->smarty->createTemplate('eval:{mailto address="me@example.com" encode="javascript_charcode"}');
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
}
@@ -78,7 +78,7 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
public function testEncodeJavascriptCharcodeWithoutMbstring()
{
Smarty::$_MBSTRING = false;
$result = "<script type=\"text/javascript\" language=\"javascript\">\n{document.write(String.fromCharCode(60,97,32,104,114,101,102,61,34,109,97,105,108,116,111,58,109,101,64,101,120,97,109,112,108,101,46,99,111,109,34,32,62,109,101,64,101,120,97,109,112,108,101,46,99,111,109,60,47,97,62))}\n</script>\n";
$result = '<script type="text/javascript">document.write(String.fromCharCode(60,97,32,104,114,101,102,61,34,109,97,105,108,116,111,58,109,101,64,101,120,97,109,112,108,101,46,99,111,109,34,32,62,109,101,64,101,120,97,109,112,108,101,46,99,111,109,60,47,97,62))</script>';
$tpl = $this->smarty->createTemplate('eval:{mailto address="me@example.com" encode="javascript_charcode"}');
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
Smarty::$_MBSTRING = true;
@@ -435,9 +435,9 @@ class CompileFunctionTest extends PHPUnit_Smarty
/**
* Test handling of function names that are a security risk
* @expectedException SmartyCompilerException
*/
public function testIllegalFunctionName() {
$this->expectException(SmartyCompilerException::class);
$this->smarty->fetch('string:{function name=\'rce(){};echo "hi";function \'}{/function}');
}
@@ -44,6 +44,30 @@ class MathTest extends PHPUnit_Smarty
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testMultipleOperators()
{
$this->smarty->disableSecurity();
$expected = "2 -- 2";
$tpl = $this->smarty->createTemplate('eval:{$x = 5}{$y = 4}{math equation="x - y + 1" x=$x y=$y} -- {math equation="5 - 4 + 1"}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testMathMaxFunctionParameters()
{
$this->smarty->disableSecurity();
$expected = max(0, 2) . ' -- ' . max(0, 2, 3);
$tpl = $this->smarty->createTemplate('eval:{$x = 0}{$y = 2}{$z = 3}{math equation="max(x, y)" x=$x y=$y} -- {math equation="max(x, y, z)" x=$x y=$y z=$z}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testMathMinFunctionParameters()
{
$this->smarty->disableSecurity();
$expected = min(1, 2) . ' -- ' . min(1, 2, 0);
$tpl = $this->smarty->createTemplate('eval:{$x = 1}{$y = 2}{$z = 0}{math equation="min(x, y)" x=$x y=$y} -- {math equation="min(x, y, z)" x=$x y=$y z=$z}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testSyntaxSin()
{
$this->smarty->disableSecurity();
@@ -107,4 +131,29 @@ class MathTest extends PHPUnit_Smarty
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="x * y" x=$x y=$y format="%0.2f"} -- {math equation="20.5 / 5" format="%0.2f"}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testBackticksIllegal()
{
$this->expectException(PHPUnit\Framework\Error\Warning::class);
$expected = "22.00";
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="`ls` x * y" x=$x y=$y}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testDollarSignsIllegal()
{
$this->expectException(PHPUnit\Framework\Error\Warning::class);
$expected = "22.00";
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="$" x=$x y=$y}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
public function testBracketsIllegal()
{
$this->expectException(PHPUnit\Framework\Error\Warning::class);
$expected = "I";
$tpl = $this->smarty->createTemplate('eval:{$x = "0"}{$y = "1"}{math equation="((y/x).(x))[x]" x=$x y=$y}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
}
@@ -96,7 +96,7 @@ class VariableStream
$v = &$GLOBALS[$this->varname];
$l = strlen($data);
$p = &$this->position;
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
return $l;
}