Skip to content

Commit 4a2c957

Browse files
committed
SECURITY: allowing for direct injection (Issue #8)
1 parent 7c7d176 commit 4a2c957

File tree

4 files changed

+12
-15
lines changed

4 files changed

+12
-15
lines changed

Diff for: Template.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ static function embrace($content, $array)
2424
$saveClosing = preg_quote(TemplateFunctions::getDelimiters()[1]);
2525
foreach ($flatArray as $flatKey => $value){
2626
$flatKey = preg_replace('/[\/\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\-]/', "\\\\$0",$flatKey);
27-
if(is_callable($value)){
28-
TemplateFunctions::registerClosure($flatKey,$value);
29-
} else {
30-
$content = preg_replace("/$saveOpening\s*$flatKey\s*$saveClosing/", $value, $content);
31-
$content = TemplateFunctions::tryClosures($flatArray, $content, false);
32-
}
27+
// PATCHED: direct function injection is not allowed anymore
28+
$content = preg_replace("/$saveOpening\s*$flatKey\s*$saveClosing/", $value, $content);
29+
$content = TemplateFunctions::tryClosures($flatArray, $content, false);
30+
3331
}
3432

3533
return $content;

Diff for: TemplateFunctions.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private static function retrieveClosurePattern($pure, $closureName)
103103
if (!$pure) {
104104
$pattern .= preg_quote(self::$registeredDelimiters[0]) . "\s*";
105105
}
106-
$pattern .= "$closureName\(([a-z0-9,\.\s]+)\)";
106+
$pattern .= "$closureName\(([a-z0-9,\.\s_]+)\)";
107107
if (!$pure) {
108108
$pattern .= "\s*" . preg_quote(self::$registeredDelimiters[1]);
109109
}
@@ -201,7 +201,6 @@ private static function evaluateTypedCondition(array $flatArray, $expression): b
201201
foreach ($flatArray as $key => $value) {
202202
$pattern = '/' . $key . '([^.]|$)/';
203203
if (preg_match($pattern, $expression, $matches)) {
204-
205204
switch (gettype($flatArray[$key])) {
206205
case 'boolean':
207206
$expression = str_replace($key, $flatArray[$key] ? 'true' : 'false', $expression);
@@ -241,11 +240,12 @@ static function nIf($content, $array)
241240
return $content;
242241
}
243242

243+
$array = Template::flattenArray($array);
244+
// important: first try closures
245+
$array = array_merge(self::$registeredClosures, $array);
244246
foreach ($hits as $hit) {
245247
$expression = $hit->getAttribute('n-if');
246-
$array = Template::flattenArray($array);
247248
$bool = self::evaluateTypedCondition($array, $expression);
248-
249249
if (!$bool) {
250250
$hit->parentNode->removeChild($hit);
251251
} else {

Diff for: composer.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
{
22
"name": "neoan3-apps/template",
33
"description": "neoan3 minimal template engine",
4-
"version": "1.1.0",
4+
"version": "1.1.1",
55
"license": "MIT",
66
"autoload": {
77
"psr-4": {
88
"Neoan3\\Apps\\": "./"
99
}
10-
1110
},
1211
"require": {
1312
"ext-openssl": "*",

Diff for: tests/TemplateTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ public function testEmbraceTypes()
113113
public function testCallback()
114114
{
115115
$array = [
116-
'myFunc' => function ($x) {
117-
return strtoupper($x);
118-
},
119116
'some' => 'value'
120117
];
118+
TemplateFunctions::registerClosure('myFunc',function($x){
119+
return strtoupper($x);
120+
});
121121
$t = Template::embraceFromFile('callback.html', $array);
122122

123123
$this->assertStringContainsString('<p>VALUE</p>', $t);

0 commit comments

Comments
 (0)