File: 0008-Safe-escaping-of-fragments-for-eval.patch

package info (click to toggle)
symfony 2.3.21%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 31,028 kB
  • sloc: php: 162,090; xml: 2,839; sh: 422; sql: 246; makefile: 78
file content (113 lines) | stat: -rw-r--r-- 5,079 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
From: Nicolas Grekas <nicolas.grekas@gmail.com>
Date: Mon, 16 Mar 2015 15:12:02 +0100
Subject: Safe escaping of fragments for eval()

https://github.com/symfony/symfony/commit/195c57e1f50765aff33137689b16e126a689056a
---
 src/Symfony/Component/HttpKernel/HttpCache/Esi.php | 62 +++++++++++-----------
 .../HttpKernel/Tests/HttpCache/EsiTest.php         |  4 +-
 2 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
index 9dd99d6..ad63267 100644
--- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
+++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
@@ -29,6 +29,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
 class Esi
 {
     private $contentTypes;
+    private $phpEscapeMap = array(
+        array('<?', '<%', '<s', '<S'),
+        array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
+    );
 
     /**
      * Constructor.
@@ -158,10 +162,34 @@ class Esi
 
         // we don't use a proper XML parser here as we can have ESI tags in a plain text response
         $content = $response->getContent();
-        $content = str_replace(array('<?', '<%'), array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>'), $content);
-        $content = preg_replace_callback('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', array($this, 'handleEsiIncludeTag'), $content);
-        $content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
         $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#', '', $content);
+        $content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
+
+        $chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
+        $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
+
+        $i = 1;
+        while (isset($chunks[$i])) {
+            $options = array();
+            preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
+            foreach ($matches as $set) {
+                $options[$set[1]] = $set[2];
+            }
+
+            if (!isset($options['src'])) {
+                throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
+            }
+
+            $chunks[$i] = sprintf('<?php echo $this->esi->handle($this, %s, %s, %s) ?>'."\n",
+                var_export($options['src'], true),
+                var_export(isset($options['alt']) ? $options['alt'] : '', true),
+                isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
+            );
+            ++$i;
+            $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
+            ++$i;
+        }
+        $content = implode('', $chunks);
 
         $response->setContent($content);
         $response->headers->set('X-Body-Eval', 'ESI');
@@ -214,32 +242,4 @@ class Esi
             }
         }
     }
-
-    /**
-     * Handles an ESI include tag (called internally).
-     *
-     * @param array $attributes An array containing the attributes.
-     *
-     * @return string The response content for the include.
-     *
-     * @throws \RuntimeException
-     */
-    private function handleEsiIncludeTag($attributes)
-    {
-        $options = array();
-        preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER);
-        foreach ($matches as $set) {
-            $options[$set[1]] = $set[2];
-        }
-
-        if (!isset($options['src'])) {
-            throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
-        }
-
-        return sprintf('<?php echo $this->esi->handle($this, %s, %s, %s) ?>'."\n",
-            var_export($options['src'], true),
-            var_export(isset($options['alt']) ? $options['alt'] : '', true),
-            isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
-        );
-    }
 }
diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
index 23e256e..8ab3d47 100644
--- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
@@ -131,10 +131,10 @@ class EsiTest extends \PHPUnit_Framework_TestCase
         $esi = new Esi();
 
         $request = Request::create('/');
-        $response = new Response('foo <?php die("foo"); ?><%= "lala" %>');
+        $response = new Response('<?php <? <% <script language=php>');
         $esi->process($request, $response);
 
-        $this->assertEquals('foo <?php echo "<?"; ?>php die("foo"); ?><?php echo "<%"; ?>= "lala" %>', $response->getContent());
+        $this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent());
     }
 
     /**