bug #25787 Yaml parser regression with comments and non-strings (alexpott)

This PR was squashed before being merged into the 3.4 branch (closes #25787).

Discussion
----------

Yaml parser regression with comments and non-strings

| Q             | A
| ------------- | ---
| Branch?       | 3.3 <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks?    | no
| Deprecations? | no <!-- don't forget to update UPGRADE-*.md files -->
| Tests pass?   | no
| Fixed tickets | #25786
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!--highly recommended for new features-->

<!--
- Bug fixes must be submitted against the lowest branch where they apply
  (lowest branches are regularly merged to upper ones so they get the fixes too).
- Features and deprecations must be submitted against the master branch.
- Replace this comment by a description of what your PR is solving.
-->

Commits
-------

a7e2a49 Yaml parser regression with comments and non-strings
This commit is contained in:
Christian Flothmann 2018-02-16 10:50:28 +01:00
commit 7bcccefb60
2 changed files with 58 additions and 37 deletions

View File

@ -422,54 +422,39 @@ class Parser
// try to parse the value as a multi-line string as a last resort
if (0 === $this->currentLineNb) {
$parseError = false;
$previousLineWasNewline = false;
$previousLineWasTerminatedWithBackslash = false;
$value = '';
foreach ($this->lines as $line) {
try {
if (isset($line[0]) && ('"' === $line[0] || "'" === $line[0])) {
$parsedLine = $line;
} else {
$parsedLine = Inline::parse($line, $flags, $this->refs);
}
if ('' === trim($line)) {
$value .= "\n";
} elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) {
$value .= ' ';
}
if (!is_string($parsedLine)) {
$parseError = true;
break;
}
if ('' !== trim($line) && '\\' === substr($line, -1)) {
$value .= ltrim(substr($line, 0, -1));
} elseif ('' !== trim($line)) {
$value .= trim($line);
}
if ('' === trim($parsedLine)) {
$value .= "\n";
} elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) {
$value .= ' ';
}
if ('' !== trim($parsedLine) && '\\' === substr($parsedLine, -1)) {
$value .= ltrim(substr($parsedLine, 0, -1));
} elseif ('' !== trim($parsedLine)) {
$value .= trim($parsedLine);
}
if ('' === trim($parsedLine)) {
$previousLineWasNewline = true;
$previousLineWasTerminatedWithBackslash = false;
} elseif ('\\' === substr($parsedLine, -1)) {
$previousLineWasNewline = false;
$previousLineWasTerminatedWithBackslash = true;
} else {
$previousLineWasNewline = false;
$previousLineWasTerminatedWithBackslash = false;
}
} catch (ParseException $e) {
$parseError = true;
break;
if ('' === trim($line)) {
$previousLineWasNewline = true;
$previousLineWasTerminatedWithBackslash = false;
} elseif ('\\' === substr($line, -1)) {
$previousLineWasNewline = false;
$previousLineWasTerminatedWithBackslash = true;
} else {
$previousLineWasNewline = false;
$previousLineWasTerminatedWithBackslash = false;
}
}
if (!$parseError) {
try {
return Inline::parse(trim($value));
} catch (ParseException $e) {
// fall-through to the ParseException thrown below
}
}

View File

@ -791,6 +791,42 @@ EOT;
$this->assertSame($expected, $this->parser->parse($yaml));
}
public function testNonStringFollowedByCommentEmbeddedInMapping()
{
$yaml = <<<'EOT'
a:
b:
{}
# comment
d:
1.1
# another comment
EOT;
$expected = array(
'a' => array(
'b' => array(),
'd' => 1.1,
),
);
$this->assertSame($expected, $this->parser->parse($yaml));
}
public function testMultiLineStringLastResortParsing()
{
$yaml = <<<'EOT'
test:
You can have things that don't look like strings here
true
yes you can
EOT;
$expected = array(
'test' => 'You can have things that don\'t look like strings here true yes you can',
);
$this->assertSame($expected, $this->parser->parse($yaml));
}
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/