Fixed quoting issues with Yaml Inline Parser

* Added test parse error in parseQuotedScalar
  * Expecting to throw tests, previously trimmed string
  * More details on issue: https://github.com/symfony/symfony/issues/4021
* Enforces single quote escaping when within string quotes
  * Shortens the scope of the validation match
  * Stricter matching rules
* Ensures double quoted strings are not parsed incorrectly
* Split quote matching into 2 types of quotes
  * Separates single and double quotes
  * Fixes intollerence for un escaped double quote
This commit is contained in:
Paul Matthews 2012-04-20 16:15:12 +01:00
parent fae4523f3b
commit 478227d9ac
2 changed files with 43 additions and 1 deletions

View File

@ -21,6 +21,8 @@ use Symfony\Component\Yaml\Exception\DumpException;
class Inline
{
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
const REGEX_SINGLE_QUOTED_STRING = '(?:\'([^\']*(?:\'\'[^\']*)*)\')(?!.*\')';
const REGEX_DOUBLE_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)")(?!.*")';
/**
* Converts a YAML string to a PHP array.
@ -196,7 +198,16 @@ class Inline
*/
static private function parseQuotedScalar($scalar, &$i)
{
if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
// Only check the current item we're dealing with (for sequences)
$subject = substr($scalar, $i);
$items = preg_split('/[\'"]\s*(?:[,:]|[}\]]\s*,)/', $subject);
$subject = substr($subject, 0, strlen($items[0]) + 1);
if (($scalar[$i] == "'"
&& !preg_match('/'.self::REGEX_SINGLE_QUOTED_STRING.'/Au', $subject, $match))
|| ($scalar[$i] == '"'
&& !preg_match('/'.self::REGEX_DOUBLE_QUOTED_STRING.'/Au', $subject, $match))
) {
throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
}

View File

@ -65,6 +65,34 @@ class InlineTest extends \PHPUnit_Framework_TestCase
$this->assertSame($value, Inline::parse(Inline::dump($value)));
}
/**
*
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException()
{
$value = "'don't do somthin' like that'";
Inline::parseScalar($value);
}
/**
*
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException()
{
$value = '"don"t do somthin" like that"';
Inline::parseScalar($value);
}
public function testParseScalarWithCorrectlyQuotedStringShouldReturnString()
{
$value = "'don''t do somthin'' like that'";
$expect = "don't do somthin' like that";
$this->assertSame($expect, Inline::parseScalar($value));
}
protected function getTestsForParse()
{
return array(
@ -124,6 +152,7 @@ class InlineTest extends \PHPUnit_Framework_TestCase
'[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),
'[foo, bar: { foo: bar }]' => array('foo', '1' => array('bar' => array('foo' => 'bar'))),
'[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
);
}
@ -167,6 +196,8 @@ class InlineTest extends \PHPUnit_Framework_TestCase
'[foo, { bar: foo }]' => array('foo', array('bar' => 'foo')),
'[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),
'[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
);
}
}