From bbb43caa1a619ddb8da943146c3e24d543e09335 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Sun, 21 Jul 2019 15:37:32 -0700 Subject: [PATCH] Fix delimiter parse error, and throw a syntax error when invalid. The mustache spec has a test case that _should_ have caught this: https://github.com/mustache/spec/blob/master/specs/delimiters.yml#L154-L158 ... But that test case only tests that an engine recognizes it as a delimiter change tag, not that it ends up changing to the correct delimiters. In our case, we were incorrectly changing to `@` and ` `. The only "invalid" case I can think of is missing delimiters, which is how that spec test was (incorrectly) parsed. Now it'll enforce that it's always called with *something* that can be used as a delimiter. --- src/Mustache/Tokenizer.php | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Mustache/Tokenizer.php b/src/Mustache/Tokenizer.php index b1f3d73..daecb7f 100644 --- a/src/Mustache/Tokenizer.php +++ b/src/Mustache/Tokenizer.php @@ -81,6 +81,7 @@ class Mustache_Tokenizer * Scan and tokenize template source. * * @throws Mustache_Exception_SyntaxException when mismatched section tags are encountered + * @throws Mustache_Exception_InvalidArgumentException when $delimiters string is invalid * * @param string $text Mustache template source to tokenize * @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null) @@ -249,6 +250,8 @@ class Mustache_Tokenizer /** * Change the current Mustache delimiters. Set new `otag` and `ctag` values. * + * @throws Mustache_Exception_SyntaxException when delimiter string is invalid + * * @param string $text Mustache template source * @param int $index Current tokenizer index * @@ -260,24 +263,37 @@ class Mustache_Tokenizer $close = '=' . $this->ctag; $closeIndex = strpos($text, $close, $index); - $this->setDelimiters(trim(substr($text, $startIndex, $closeIndex - $startIndex))); - - $this->tokens[] = array( + $token = array( self::TYPE => self::T_DELIM_CHANGE, self::LINE => $this->line, ); + try { + $this->setDelimiters(trim(substr($text, $startIndex, $closeIndex - $startIndex))); + } catch (Mustache_Exception_InvalidArgumentException $e) { + throw new Mustache_Exception_SyntaxException($e->getMessage(), $token); + } + + $this->tokens[] = $token; + return $closeIndex + strlen($close) - 1; } /** * Set the current Mustache `otag` and `ctag` delimiters. * + * @throws Mustache_Exception_InvalidArgumentException when delimiter string is invalid + * * @param string $delimiters */ private function setDelimiters($delimiters) { - list($otag, $ctag) = explode(' ', $delimiters); + if (!preg_match('/^\s*(\S+)\s+(\S+)\s*$/', $delimiters, $matches)) { + throw new Mustache_Exception_InvalidArgumentException(sprintf('Invalid delimiters: %s', $delimiters)); + } + + list($_, $otag, $ctag) = $matches; + $this->otag = $otag; $this->ctag = $ctag; $this->otagLen = strlen($otag);