From 1da7336648923301551b3ada582fe19b7ee589eb Mon Sep 17 00:00:00 2001
From: Nikita Hovratov <nikita.h@live.de>
Date: Wed, 20 Sep 2023 16:37:19 +0200
Subject: [PATCH] [BUGFIX] Handle missing image dimensions gracefully
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Just like SvgImageProcessor, DeferredBackendImageProcessor now also
catches the exception, which is thrown, when image dimensions equal
zero and falls back to 64x64 image dimension. This enables editors to
correct bad image cropping without the need to do it in the database.

To be more specific, a new Exception ZeroImageDimensionException is
added, which is used in both processors now.

The image cropping editor is already fixed to only allow a minimum
dimension of 10x10. However, already corrupted files can not be
accessed without this patch.

Resolves: #93807
Related: #99943
Releases: main, 12.4, 11.5
Change-Id: I259c365052dd02110d43418ba48b768bbe073fc1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/81133
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
---
 .../DeferredBackendImageProcessor.php         |  8 +++++-
 .../Exception/ZeroImageDimensionException.php | 28 +++++++++++++++++++
 .../core/Classes/Imaging/ImageDimension.php   |  3 +-
 .../Resource/Processing/SvgImageProcessor.php |  3 +-
 4 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 typo3/sysext/core/Classes/Imaging/Exception/ZeroImageDimensionException.php

diff --git a/typo3/sysext/backend/Classes/Resource/Processing/DeferredBackendImageProcessor.php b/typo3/sysext/backend/Classes/Resource/Processing/DeferredBackendImageProcessor.php
index 23f1665b29dc..1237d52d98b6 100644
--- a/typo3/sysext/backend/Classes/Resource/Processing/DeferredBackendImageProcessor.php
+++ b/typo3/sysext/backend/Classes/Resource/Processing/DeferredBackendImageProcessor.php
@@ -21,6 +21,7 @@ use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Http\ApplicationType;
+use TYPO3\CMS\Core\Imaging\Exception\ZeroImageDimensionException;
 use TYPO3\CMS\Core\Imaging\ImageDimension;
 use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
 use TYPO3\CMS\Core\Resource\Processing\ProcessorInterface;
@@ -48,7 +49,12 @@ class DeferredBackendImageProcessor implements ProcessorInterface
 
     public function processTask(TaskInterface $task): void
     {
-        $imageDimension = ImageDimension::fromProcessingTask($task);
+        try {
+            $imageDimension = ImageDimension::fromProcessingTask($task);
+        } catch (ZeroImageDimensionException $e) {
+            // To not fail image processing, we just assume an image dimension here
+            $imageDimension = new ImageDimension(64, 64);
+        }
         $processedFile = $task->getTargetFile();
         if (!$processedFile->isPersisted()) {
             // For now, we need to persist the processed file in the repository to be able to reference its uid
diff --git a/typo3/sysext/core/Classes/Imaging/Exception/ZeroImageDimensionException.php b/typo3/sysext/core/Classes/Imaging/Exception/ZeroImageDimensionException.php
new file mode 100644
index 000000000000..afc706757e65
--- /dev/null
+++ b/typo3/sysext/core/Classes/Imaging/Exception/ZeroImageDimensionException.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * 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!
+ */
+
+namespace TYPO3\CMS\Core\Imaging\Exception;
+
+use TYPO3\CMS\Core\Exception;
+
+/**
+ * This exception is thrown when an image is tasked to be processed with
+ * dimensions of zero.
+ */
+class ZeroImageDimensionException extends Exception
+{
+}
diff --git a/typo3/sysext/core/Classes/Imaging/ImageDimension.php b/typo3/sysext/core/Classes/Imaging/ImageDimension.php
index e5e62136abb5..abdeb25c7228 100644
--- a/typo3/sysext/core/Classes/Imaging/ImageDimension.php
+++ b/typo3/sysext/core/Classes/Imaging/ImageDimension.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Imaging;
 
+use TYPO3\CMS\Core\Imaging\Exception\ZeroImageDimensionException;
 use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
 use TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper;
@@ -73,7 +74,7 @@ class ImageDimension
             );
         }
         if ($imageDimension->width <= 0 || $imageDimension->height <= 0) {
-            throw new \BadMethodCallException('Width and height of the image must be greater than zero', 1597310560);
+            throw new ZeroImageDimensionException('Width and height of the image must be greater than zero.', 1597310560);
         }
         $result = GeneralUtility::makeInstance(GraphicalFunctions::class)->getImageScale(
             [
diff --git a/typo3/sysext/core/Classes/Resource/Processing/SvgImageProcessor.php b/typo3/sysext/core/Classes/Resource/Processing/SvgImageProcessor.php
index 4a58d4916909..6fe9d31646e9 100644
--- a/typo3/sysext/core/Classes/Resource/Processing/SvgImageProcessor.php
+++ b/typo3/sysext/core/Classes/Resource/Processing/SvgImageProcessor.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Resource\Processing;
 
+use TYPO3\CMS\Core\Imaging\Exception\ZeroImageDimensionException;
 use TYPO3\CMS\Core\Imaging\ImageDimension;
 
 /**
@@ -44,7 +45,7 @@ class SvgImageProcessor implements ProcessorInterface
         $task->getTargetFile()->setUsesOriginalFile();
         try {
             $imageDimension = ImageDimension::fromProcessingTask($task);
-        } catch (\Throwable $e) {
+        } catch (ZeroImageDimensionException $e) {
             // To not fail image processing, we just assume an SVG image dimension here
             $imageDimension = new ImageDimension(64, 64);
         }
-- 
GitLab