Explorar el Código

Throw syntax exception for unclosed tags.

Fixes #395
Justin Hileman hace 3 años
padre
commit
64e5609d0e
Se han modificado 2 ficheros con 70 adiciones y 0 borrados
  1. 31 0
      src/Mustache/Tokenizer.php
  2. 39 0
      test/Mustache/Test/TokenizerTest.php

+ 31 - 0
src/Mustache/Tokenizer.php

@@ -215,6 +215,10 @@ class Mustache_Tokenizer
             }
         }
 
+        if ($this->state !== self::IN_TEXT) {
+            $this->throwUnclosedTagException();
+        }
+
         $this->flushBuffer();
 
         // Restore the user's encoding...
@@ -279,6 +283,10 @@ class Mustache_Tokenizer
         $close      = '=' . $this->ctag;
         $closeIndex = strpos($text, $close, $index);
 
+        if ($closeIndex === false) {
+            $this->throwUnclosedTagException();
+        }
+
         $token = array(
             self::TYPE => self::T_DELIM_CHANGE,
             self::LINE => $this->line,
@@ -333,6 +341,10 @@ class Mustache_Tokenizer
     private function addPragma($text, $index)
     {
         $end    = strpos($text, $this->ctag, $index);
+        if ($end === false) {
+            $this->throwUnclosedTagException();
+        }
+
         $pragma = trim(substr($text, $index + 2, $end - $index - 2));
 
         // Pragmas are hoisted to the front of the template.
@@ -344,4 +356,23 @@ class Mustache_Tokenizer
 
         return $end + $this->ctagLen - 1;
     }
+
+    private function throwUnclosedTagException()
+    {
+        $name = trim($this->buffer);
+        if ($name !== '') {
+            $msg = sprintf('Unclosed tag: %s on line %d', $name, $this->line);
+        } else {
+            $msg = sprintf('Unclosed tag on line %d', $this->line);
+        }
+
+        throw new Mustache_Exception_SyntaxException($msg, array(
+            self::TYPE  => $this->tagType,
+            self::NAME  => $name,
+            self::OTAG  => $this->otag,
+            self::CTAG  => $this->ctag,
+            self::LINE  => $this->line,
+            self::INDEX => $this->seenTag - $this->otagLen,
+        ));
+    }
 }

+ 39 - 0
test/Mustache/Test/TokenizerTest.php

@@ -351,4 +351,43 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
             ),
         );
     }
+
+    /**
+     * @dataProvider getUnclosedTags
+     * @expectedException Mustache_Exception_SyntaxException
+     */
+    public function testUnclosedTagsThrowExceptions($text)
+    {
+        $tokenizer = new Mustache_Tokenizer();
+        $tokenizer->scan($text, null);
+    }
+
+    public function getUnclosedTags()
+    {
+        return array(
+            array('{{ name'),
+            array('{{ name }'),
+            array('{{{ name'),
+            array('{{{ name }'),
+            array('{{& name'),
+            array('{{& name }'),
+            array('{{# name'),
+            array('{{# name }'),
+            array('{{^ name'),
+            array('{{^ name }'),
+            array('{{/ name'),
+            array('{{/ name }'),
+            array('{{> name'),
+            array('{{< name'),
+            array('{{> name }'),
+            array('{{< name }'),
+            array('{{$ name'),
+            array('{{$ name }'),
+            array('{{= <% %>'),
+            array('{{= <% %>='),
+            array('{{= <% %>=}'),
+            array('{{% name'),
+            array('{{% name }'),
+        );
+    }
 }