From 4a5fa034b2fd3cefcdd1b82d03905dbee14b7012 Mon Sep 17 00:00:00 2001
From: Georg Ringer <georg.ringer@gmail.com>
Date: Fri, 28 Feb 2020 12:20:50 +0100
Subject: [PATCH] [BUGFIX] Catch possible exceptions while loading YAML files
 via import

If an error happens during loading YAML files, e.g. because the path is
wrong or the used extension has been deactivated, the website must still
be working.

The error is now logged as error instead.

Resolves: #88993
Releases: master, 9.5
Change-Id: I0103fac53a6f1ff6216bdc11961ffe76fea8a9b4
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61761
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
---
 .../Exception/YamlFileLoadingException.php    | 21 ++++++++++++++
 .../Loader/Exception/YamlParseException.php   | 21 ++++++++++++++
 .../Configuration/Loader/YamlFileLoader.php   | 29 +++++++++++++------
 .../Unit/Mvc/Configuration/YamlSourceTest.php |  1 +
 4 files changed, 63 insertions(+), 9 deletions(-)
 create mode 100644 typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlFileLoadingException.php
 create mode 100644 typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlParseException.php

diff --git a/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlFileLoadingException.php b/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlFileLoadingException.php
new file mode 100644
index 000000000000..98b7ac42568a
--- /dev/null
+++ b/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlFileLoadingException.php
@@ -0,0 +1,21 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Core\Configuration\Loader\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+class YamlFileLoadingException extends \RuntimeException
+{
+}
diff --git a/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlParseException.php b/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlParseException.php
new file mode 100644
index 000000000000..62da0845d75a
--- /dev/null
+++ b/typo3/sysext/core/Classes/Configuration/Loader/Exception/YamlParseException.php
@@ -0,0 +1,21 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Core\Configuration\Loader\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+class YamlParseException extends \RuntimeException
+{
+}
diff --git a/typo3/sysext/core/Classes/Configuration/Loader/YamlFileLoader.php b/typo3/sysext/core/Classes/Configuration/Loader/YamlFileLoader.php
index bb320e53530a..d03639b9e948 100644
--- a/typo3/sysext/core/Classes/Configuration/Loader/YamlFileLoader.php
+++ b/typo3/sysext/core/Classes/Configuration/Loader/YamlFileLoader.php
@@ -14,7 +14,12 @@ namespace TYPO3\CMS\Core\Configuration\Loader;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Yaml\Exception\ParseException;
 use Symfony\Component\Yaml\Yaml;
+use TYPO3\CMS\Core\Configuration\Loader\Exception\YamlFileLoadingException;
+use TYPO3\CMS\Core\Configuration\Loader\Exception\YamlParseException;
 use TYPO3\CMS\Core\Configuration\Processor\PlaceholderProcessorList;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -37,8 +42,10 @@ use TYPO3\CMS\Core\Utility\PathUtility;
  *
  * - Environment placeholder values set via %env(option)% will be replaced by env variables of the same name
  */
-class YamlFileLoader
+class YamlFileLoader implements LoggerAwareInterface
 {
+    use LoggerAwareTrait;
+
     public const PROCESS_PLACEHOLDERS = 1;
     public const PROCESS_IMPORTS = 2;
 
@@ -74,7 +81,7 @@ class YamlFileLoader
         $content = Yaml::parse($content);
 
         if (!is_array($content)) {
-            throw new \RuntimeException(
+            throw new YamlParseException(
                 'YAML file "' . $fileName . '" could not be parsed into valid syntax, probably empty?',
                 1497332874
             );
@@ -107,7 +114,7 @@ class YamlFileLoader
      * @param string $fileName either relative to TYPO3's base project folder or prefixed with EXT:...
      * @param string|null $currentFileName when called recursively this contains the absolute file name of the file that included this file
      * @return string the contents of the file
-     * @throws \RuntimeException when the file was not accessible
+     * @throws YamlFileLoadingException when the file was not accessible
      */
     protected function getStreamlinedFileName(string $fileName, ?string $currentFileName): string
     {
@@ -121,7 +128,7 @@ class YamlFileLoader
                     $fileName
                 );
                 if (!GeneralUtility::isAllowedAbsPath($streamlinedFileName)) {
-                    throw new \RuntimeException(
+                    throw new YamlFileLoadingException(
                         'Referencing a file which is outside of TYPO3s main folder',
                         1560319866
                     );
@@ -131,7 +138,7 @@ class YamlFileLoader
             $streamlinedFileName = GeneralUtility::getFileAbsFileName($fileName);
         }
         if (!$streamlinedFileName) {
-            throw new \RuntimeException('YAML File "' . $fileName . '" could not be loaded', 1485784246);
+            throw new YamlFileLoadingException('YAML File "' . $fileName . '" could not be loaded', 1485784246);
         }
         return $streamlinedFileName;
     }
@@ -147,10 +154,14 @@ class YamlFileLoader
     {
         if (isset($content['imports']) && is_array($content['imports'])) {
             foreach ($content['imports'] as $import) {
-                $import = $this->processPlaceholders($import, $import);
-                $importedContent = $this->loadAndParse($import['resource'], $fileName);
-                // override the imported content with the one from the current file
-                $content = ArrayUtility::replaceAndAppendScalarValuesRecursive($importedContent, $content);
+                try {
+                    $import = $this->processPlaceholders($import, $import);
+                    $importedContent = $this->loadAndParse($import['resource'], $fileName);
+                    // override the imported content with the one from the current file
+                    $content = ArrayUtility::replaceAndAppendScalarValuesRecursive($importedContent, $content);
+                } catch (ParseException|YamlParseException|YamlFileLoadingException $exception) {
+                    $this->logger->error($exception->getMessage(), ['exception' => $exception]);
+                }
             }
             unset($content['imports']);
         }
diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php
index 471ae0c943b8..1a3fb8f7800b 100644
--- a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php
+++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php
@@ -24,6 +24,7 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
  */
 class YamlSourceTest extends UnitTestCase
 {
+    protected $resetSingletonInstances = true;
 
     /**
      * @test
-- 
GitLab