From fb9b3e33a468113665379352cf7a49104458a085 Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Wed, 5 Jul 2023 13:10:41 +0200
Subject: [PATCH] [BUGFIX] Avoid SQL errors in PageRepository->versionOL

This change adds an additional guard clause check
to avoid SQL errors when an invalid row is entered.

Resolves: #98189
Releases: main, 12.4, 11.5
Change-Id: Iecb12b9c6ef97fb603c8b720d5e2be7433543637
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79738
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Benni Mack <benni@typo3.org>
---
 .../Domain/Repository/PageRepository.php      |  4 +--
 .../Domain/Repository/PageRepositoryTest.php  | 30 +++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
index a66410a8ddc8..c3f56f896fc9 100644
--- a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
+++ b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
@@ -1677,14 +1677,14 @@ class PageRepository implements LoggerAwareInterface
      */
     public function versionOL($table, &$row, $unsetMovePointers = false, $bypassEnableFieldsCheck = false)
     {
-        if ($this->versioningWorkspaceId > 0 && is_array($row)) {
+        if ($this->versioningWorkspaceId > 0 && is_array($row) && $row !== [] && isset($row['uid'], $row['t3ver_oid'])) {
             // implode(',',array_keys($row)) = Using fields from original record to make
             // sure no additional fields are selected. This is best for eg. getPageOverlay()
             // Computed properties are excluded since those would lead to SQL errors.
             $fieldNames = implode(',', array_keys($this->purgeComputedProperties($row)));
             // will overlay any incoming moved record with the live record, which in turn
             // will be overlaid with its workspace version again to fetch both PID fields.
-            $incomingRecordIsAMoveVersion = (int)($row['t3ver_oid'] ?? 0) > 0 && (int)($row['t3ver_state'] ?? 0) === VersionState::MOVE_POINTER;
+            $incomingRecordIsAMoveVersion = (int)($row['t3ver_oid']) > 0 && (int)($row['t3ver_state'] ?? 0) === VersionState::MOVE_POINTER;
             if ($incomingRecordIsAMoveVersion) {
                 // Fetch the live version again if the given $row is a move pointer, so we know the original PID
                 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
diff --git a/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php b/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
index 5dee74777849..ed13d18ebabe 100644
--- a/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
+++ b/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
@@ -650,4 +650,34 @@ final class PageRepositoryTest extends FunctionalTestCase
         self::assertSame('Translated #2', $overlaidRecord['header']);
         self::assertNull($overlaidRecord['bodytext']);
     }
+
+    /**
+     * @return array<string, array{0: array<string, int>}>
+     */
+    public static function invalidRowForVersionOLDataProvider(): array
+    {
+        return [
+            'no uid and no t3ver_oid' => [[]],
+            'zero uid and no t3ver_oid' => [['uid' => 0]],
+            'positive uid and no t3ver_oid' => [['uid' => 1]],
+            'no uid but t3ver_oid' => [['t3ver_oid' => 1]],
+        ];
+    }
+
+    /**
+     * @test
+     * @param array<string, int> $input
+     * @dataProvider invalidRowForVersionOLDataProvider
+     */
+    public function versionOLForAnInvalidRowUnchangedRowData(array $input): void
+    {
+        $context = new Context();
+        $context->setAspect('workspace', new WorkspaceAspect(4));
+        $subject = new PageRepository($context);
+        $originalInput = $input;
+
+        $subject->versionOL('pages', $input);
+
+        self::assertSame($originalInput, $input);
+    }
 }
-- 
GitLab