Skip to content

PREG_BACKTRACK_LIMIT_ERROR in Yaml parser #20411

Closed
@RichardBradley

Description

@RichardBradley

A YAML string with too many backslash escapes can trigger a PREG_BACKTRACK_LIMIT_ERROR error in the Yaml parser.

Steps to reproduce:

Run the following unit test:

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Yaml\Yaml;

class YamlParserBacktrackLimitTest extends WebTestCase
{
    public function testYamlQuotedString() {

        $foo = str_repeat("x\r\n\\\"x\"x", 1000);
        $yamlString = Yaml::dump(["foo" => $foo]);

        $arrayFromYaml = Yaml::parse($yamlString);

        $this->assertEquals($foo, $arrayFromYaml['foo']);
    }
}

Observed behaviour

This test will pass if you reduce the "1000" constant to "100", and fail as-is.

The reported exception is:

Malformed inline YAML string ("x\r\n\\\ ...
at n/a
        in ...\vendor\symfony\symfony\src\Symfony\Component\Yaml\Inline.php line 344

The relevant source is here:

       const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
...
        if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
            throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)));
        }

Expected behaviour

  1. The test should pass, i.e. the YAML should be parseable, since it fits in memory and is well formed.

  2. The exception thrown by Symfony if the preg_match fails due to PREG_BACKTRACK_LIMIT_ERROR should indicate that the op failed due to resource exhaustion and not incorrectly blame invalid YAML.

Suggested fix

I suspect that changing the REGEX_QUOTED_STRING regex to use possessive qualifiers will probably fix bug 1 above without otherwise changing the YAML parser's behaviour.

Fixing bug 2 above needs a call to preg_last_error() after each "preg_match" call in Symfony code, which will be tedious.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions