diff --git a/core/lib/Drupal/Component/Serialization/YamlSymfony.php b/core/lib/Drupal/Component/Serialization/YamlSymfony.php index d35e09c..1cbebff 100644 --- a/core/lib/Drupal/Component/Serialization/YamlSymfony.php +++ b/core/lib/Drupal/Component/Serialization/YamlSymfony.php @@ -30,13 +30,34 @@ public static function encode($data) { * {@inheritdoc} */ public static function decode($raw) { + // Workaround for PHP 7 bug #70110 that causes the symfony yaml parser to + // fail on some strings, for example those containing a lot of newlines. + // @see https://bugs.php.net/bug.php?id=70110 + // @see https://www.drupal.org/node/2792877 + $reactivate_pcre_jit = 0; + if (version_compare(phpversion(), '7', '>=')) { + if ($reactivate_pcre_jit = ini_get('pcre.jit')) { + // Turn off jit while parsing YAML files. + ini_set('pcre.jit', 0); + } + } + try { $yaml = new Parser(); // Make sure we have a single trailing newline. A very simple config like // 'foo: bar' with no newline will fail to parse otherwise. - return $yaml->parse($raw, SymfonyYaml::PARSE_EXCEPTION_ON_INVALID_TYPE); + $parsed = $yaml->parse($raw, SymfonyYaml::PARSE_EXCEPTION_ON_INVALID_TYPE); + if ($reactivate_pcre_jit) { + // Turn back on jit for performance. + ini_set('pcre.jit', 1); + } + return $parsed; } catch (\Exception $e) { + if ($reactivate_pcre_jit) { + // Turn back on jit for performance. + ini_set('pcre.jit', 1); + } throw new InvalidDataTypeException($e->getMessage(), $e->getCode(), $e); } } diff --git a/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php b/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php index 86c818c..89ac70d 100644 --- a/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php +++ b/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php @@ -75,4 +75,20 @@ public function testObjectSupportDisabled() { YamlSymfony::encode([$object]); } + /** + * Tests that preg jit compiler doesn't break decoding strings with newlines. + * + * @covers ::decode + */ + public function testNewlines() { + $string = str_repeat('\n', 2700); + $yaml = 'string: "' . $string . '"'; + $config = YamlSymfony::decode($yaml); + $this->assertEquals(str_repeat("\n", 2700), $config['string']); + + $string = str_repeat('\n', 2800); + $yaml = 'string: "' . $string . '"'; + $config = YamlSymfony::decode($yaml); + $this->assertEquals(str_repeat("\n", 2800), $config['string']); + } }