Sandbox `foreachVars` in templates
authorAlexander Ebert <ebert@woltlab.com>
Sun, 8 Aug 2021 09:29:26 +0000 (11:29 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 8 Sep 2021 11:57:10 +0000 (13:57 +0200)
Nesting the same template inside a `foreach` loop that is also accessed inside the nested call will overwrite the values from the outer template due to identical identifiers being used.

The sandbox did not protected `$this->foreachVars` despite being stateful.

See #4431
Fixes #4444

wcfsetup/install/files/lib/system/template/TemplateEngine.class.php

index c72d8e2fec5a258dc9328a507470327e4ba92117..998ef3e1474a44c7d0dfe2fa2e040aa5e7cf94f7 100755 (executable)
@@ -521,8 +521,11 @@ class TemplateEngine extends SingletonFactory {
         * Enables execution in sandbox.
         */
        public function enableSandbox() {
-               $index = count($this->sandboxVars);
-               $this->sandboxVars[$index] = $this->v;
+               $index = \count($this->sandboxVars);
+        $this->sandboxVars[$index] = [
+            'foreachVars' => $this->foreachVars,
+            'v' => $this->v,
+        ];
        }
        
        /**
@@ -532,8 +535,10 @@ class TemplateEngine extends SingletonFactory {
                if (empty($this->sandboxVars)) {
                        throw new SystemException('TemplateEngine is currently not running in a sandbox.');
                }
-               
-               $this->v = array_pop($this->sandboxVars);
+
+        $values = \array_pop($this->sandboxVars);
+        $this->foreachVars = $values['foreachVars'];
+        $this->v = $values['v'];
        }
        
        /**