diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
index 3e1818a94bf29ee2be1f1f21bf54e98d544f16fa..8557d591e1915b0a53943db45b8d713b73103ef1 100644
--- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php
+++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
@@ -1415,14 +1415,15 @@ class BackendUtility
                 $recordTitle = $params['title'];
             } else {
                 // No userFunc: Build label
+                $ctrlLabel = $GLOBALS['TCA'][$table]['ctrl']['label'] ?? '';
                 $recordTitle = self::getProcessedValue(
                     $table,
-                    $GLOBALS['TCA'][$table]['ctrl']['label'],
-                    $row[$GLOBALS['TCA'][$table]['ctrl']['label']],
+                    $ctrlLabel,
+                    $row[$ctrlLabel] ?? '',
                     0,
                     false,
                     false,
-                    $row['uid'],
+                    $row['uid'] ?? null,
                     $forceResult
                 ) ?? '';
                 if (!empty($GLOBALS['TCA'][$table]['ctrl']['label_alt'])
@@ -1434,7 +1435,7 @@ class BackendUtility
                         $tA[] = $recordTitle;
                     }
                     foreach ($altFields as $fN) {
-                        $recordTitle = trim(strip_tags($row[$fN]));
+                        $recordTitle = trim(strip_tags($row[$fN] ?? ''));
                         if ((string)$recordTitle !== '') {
                             $recordTitle = self::getProcessedValue($table, $fN, $recordTitle, 0, false, false, $row['uid']);
                             if (!$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
@@ -1443,7 +1444,7 @@ class BackendUtility
                             $tA[] = $recordTitle;
                         }
                     }
-                    if ($GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
+                    if ($GLOBALS['TCA'][$table]['ctrl']['label_alt_force'] ?? false) {
                         $recordTitle = implode(', ', $tA);
                     }
                 }
diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 11c07f106f478d978cc75bfe2faddc7909c4a453..ca1772c971cd1f22b34b27976539829f04d76976 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -1330,7 +1330,7 @@ class DataHandler implements LoggerAwareInterface
                             $originalLanguage_diffStorage[$field] = (string)($originalLanguageRecord[$field] ?? '');
                             $diffStorageFlag = true;
                         }
-                    } elseif ($GLOBALS['TCA'][$table]['ctrl']['origUid'] === $field) {
+                    } elseif (isset($GLOBALS['TCA'][$table]['ctrl']['origUid']) && $GLOBALS['TCA'][$table]['ctrl']['origUid'] === $field) {
                         // Allow value for original UID to pass by...
                         $fieldArray[$field] = $fieldValue;
                     }
@@ -1627,7 +1627,7 @@ class DataHandler implements LoggerAwareInterface
                 $evalCodesArray = GeneralUtility::trimExplode(',', $tcaFieldConf['eval'], true);
                 $this->runtimeCache->set($cacheId, $evalCodesArray);
             }
-            $valueArray = $this->checkValue_text_Eval($value, $evalCodesArray, $tcaFieldConf['is_in']);
+            $valueArray = $this->checkValue_text_Eval($value, $evalCodesArray, $tcaFieldConf['is_in'] ?? '');
         } else {
             $valueArray = ['value' => $value];
         }
@@ -1806,7 +1806,7 @@ class DataHandler implements LoggerAwareInterface
      */
     protected function checkValueForCheck($res, $value, $tcaFieldConf, $table, $id, $realPid, $field)
     {
-        $items = $tcaFieldConf['items'];
+        $items = $tcaFieldConf['items'] ?? null;
         if (!empty($tcaFieldConf['itemsProcFunc'])) {
             /** @var ItemProcessingService $processingService */
             $processingService = GeneralUtility::makeInstance(ItemProcessingService::class);
@@ -1888,7 +1888,7 @@ class DataHandler implements LoggerAwareInterface
         }
 
         // if no value was found and an itemsProcFunc is defined, check that for the value
-        if ($tcaFieldConf['itemsProcFunc'] && empty($res['value'])) {
+        if (!empty($tcaFieldConf['itemsProcFunc']) && empty($res['value'])) {
             $processingService = GeneralUtility::makeInstance(ItemProcessingService::class);
             $processedItems = $processingService->getProcessingItems(
                 $table,
@@ -3133,7 +3133,7 @@ class DataHandler implements LoggerAwareInterface
         foreach ($row as $field => $value) {
             if (!in_array($field, $nonFields, true)) {
                 // Get TCA configuration for the field:
-                $conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
+                $conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'] ?? [];
                 // Preparation/Processing of the value:
                 // "pid" is hardcoded of course:
                 // isset() won't work here, since values can be NULL in each of the arrays
@@ -3148,11 +3148,18 @@ class DataHandler implements LoggerAwareInterface
                     $value = $copyAfterFields[$field];
                 } else {
                     // Hide at copy may override:
-                    if ($first && $field == $enableField && $GLOBALS['TCA'][$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) {
+                    if ($first && $field == $enableField
+                        && ($GLOBALS['TCA'][$table]['ctrl']['hideAtCopy'] ?? false)
+                        && !$this->neverHideAtCopy
+                        && !($tE['disableHideAtCopy'] ?? false)
+                    ) {
                         $value = 1;
                     }
                     // Prepend label on copy:
-                    if ($first && $field == $headerField && $GLOBALS['TCA'][$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) {
+                    if ($first && $field == $headerField
+                        && ($GLOBALS['TCA'][$table]['ctrl']['prependAtCopy'] ?? false)
+                        && !($tE['disablePrependAtCopy'] ?? false)
+                    ) {
                         $value = $this->getCopyHeader($table, $this->resolvePid($table, $destPid), $field, $this->clearPrefixFromValue($table, $value), 0);
                     }
                     // Processing based on the TCA config field type (files, references, flexforms...)
@@ -3163,11 +3170,11 @@ class DataHandler implements LoggerAwareInterface
             }
         }
         // Overriding values:
-        if ($GLOBALS['TCA'][$table]['ctrl']['editlock']) {
+        if ($GLOBALS['TCA'][$table]['ctrl']['editlock'] ?? false) {
             $data[$table][$theNewID][$GLOBALS['TCA'][$table]['ctrl']['editlock']] = 0;
         }
         // Setting original UID:
-        if ($GLOBALS['TCA'][$table]['ctrl']['origUid']) {
+        if ($GLOBALS['TCA'][$table]['ctrl']['origUid'] ?? false) {
             $data[$table][$theNewID][$GLOBALS['TCA'][$table]['ctrl']['origUid']] = $uid;
         }
         // Do the copy by simply submitting the array through DataHandler:
@@ -3452,7 +3459,7 @@ class DataHandler implements LoggerAwareInterface
         foreach ($row as $field => $value) {
             if (!in_array($field, $nonFields, true)) {
                 // Get TCA configuration for the field:
-                $conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
+                $conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'] ?? false;
                 if (is_array($conf)) {
                     // Processing based on the TCA config field type (files, references, flexforms...)
                     $value = $this->copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $row, $conf, $pid, 0, $workspaceOptions);
@@ -3463,7 +3470,7 @@ class DataHandler implements LoggerAwareInterface
         }
         $row['pid'] = $pid;
         // Setting original UID:
-        if ($GLOBALS['TCA'][$table]['ctrl']['origUid']) {
+        if ($GLOBALS['TCA'][$table]['ctrl']['origUid'] ?? '') {
             $row[$GLOBALS['TCA'][$table]['ctrl']['origUid']] = $uid;
         }
         // Do the copy by internal function
@@ -3559,7 +3566,7 @@ class DataHandler implements LoggerAwareInterface
             $value = $this->copyRecord_processInline($table, $uid, $field, $value, $row, $conf, $realDestPid, $language, $workspaceOptions);
         }
         // For "flex" fieldtypes we need to traverse the structure for two reasons: If there are file references they have to be prepended with absolute paths and if there are database reference they MIGHT need to be remapped (still done in remapListedDBRecords())
-        if ($conf['type'] === 'flex') {
+        if (isset($conf['type']) && $conf['type'] === 'flex') {
             // Get current value array:
             $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
             $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
@@ -3594,7 +3601,7 @@ class DataHandler implements LoggerAwareInterface
     protected function copyRecord_processManyToMany($table, $uid, $field, $value, $conf, $language)
     {
         $allowedTables = $conf['type'] === 'group' ? $conf['allowed'] : $conf['foreign_table'];
-        $prependName = $conf['type'] === 'group' ? $conf['prepend_tname'] : '';
+        $prependName = $conf['type'] === 'group' ? ($conf['prepend_tname'] ?? '') : '';
         $mmTable = isset($conf['MM']) && $conf['MM'] ? $conf['MM'] : '';
         $localizeForeignTable = isset($conf['foreign_table']) && BackendUtility::isTableLocalizable($conf['foreign_table']);
         // Localize referenced records of select fields:
@@ -4143,7 +4150,7 @@ class DataHandler implements LoggerAwareInterface
         if (is_array($row) && (int)$destPid !== (int)$row['pid']) {
             $conf = $GLOBALS['TCA'][$table]['columns'];
             foreach ($row as $field => $value) {
-                $this->moveRecord_procBasedOnFieldType($table, $uid, $destPid, $field, $value, $conf[$field]['config']);
+                $this->moveRecord_procBasedOnFieldType($table, $uid, $destPid, $field, $value, $conf[$field]['config'] ?? []);
             }
         }
     }
@@ -4162,7 +4169,7 @@ class DataHandler implements LoggerAwareInterface
     public function moveRecord_procBasedOnFieldType($table, $uid, $destPid, $field, $value, $conf)
     {
         $dbAnalysis = null;
-        if ($conf['type'] === 'inline') {
+        if (!empty($conf['type']) && $conf['type'] === 'inline') {
             $foreign_table = $conf['foreign_table'];
             $moveChildrenWithParent = !isset($conf['behaviour']['disableMovingChildrenWithParent']) || !$conf['behaviour']['disableMovingChildrenWithParent'];
             if ($foreign_table && $moveChildrenWithParent) {
@@ -4340,18 +4347,19 @@ class DataHandler implements LoggerAwareInterface
         }
         // Copy the type (if defined in both tables) from the original record so that translation has same type as original record
         if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) {
-            $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['type']] = $row[$GLOBALS['TCA'][$table]['ctrl']['type']];
+            // @todo: Possible bug here? type can be something like 'table:field', which is then null in $row, writing null to $overrideValues
+            $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['type']] = $row[$GLOBALS['TCA'][$table]['ctrl']['type']] ?? null;
         }
         // Set exclude Fields:
         foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fCfg) {
             $translateToMsg = '';
             // Check if we are just prefixing:
-            if ($fCfg['l10n_mode'] === 'prefixLangTitle') {
+            if (isset($fCfg['l10n_mode']) && $fCfg['l10n_mode'] === 'prefixLangTitle') {
                 if (($fCfg['config']['type'] === 'text' || $fCfg['config']['type'] === 'input') && (string)$row[$fN] !== '') {
                     [$tscPID] = BackendUtility::getTSCpid($table, $uid, '');
                     $TSConfig = BackendUtility::getPagesTSconfig($tscPID)['TCEMAIN.'] ?? [];
                     $tE = $this->getTableEntries($table, $TSConfig);
-                    if (!empty($TSConfig['translateToMessage']) && !$tE['disablePrependAtCopy']) {
+                    if (!empty($TSConfig['translateToMessage']) && !($tE['disablePrependAtCopy'] ?? false)) {
                         $translateToMsg = $this->getLanguageService()->sL($TSConfig['translateToMessage']);
                         $translateToMsg = @sprintf($translateToMsg, $langRec['title']);
                     }
@@ -5002,7 +5010,7 @@ class DataHandler implements LoggerAwareInterface
             return;
         }
         foreach ($row as $field => $value) {
-            $this->deleteRecord_procBasedOnFieldType($table, $uid, $field, $value, $conf[$field]['config']);
+            $this->deleteRecord_procBasedOnFieldType($table, $uid, $field, $value, $conf[$field]['config'] ?? []);
         }
     }
 
@@ -5018,8 +5026,11 @@ class DataHandler implements LoggerAwareInterface
      * @see deleteRecord()
      * @internal should only be used from within DataHandler
      */
-    public function deleteRecord_procBasedOnFieldType($table, $uid, $field, $value, $conf)
+    public function deleteRecord_procBasedOnFieldType($table, $uid, $field, $value, $conf): void
     {
+        if (!isset($conf['type'])) {
+            return;
+        }
         if ($conf['type'] === 'inline') {
             $foreign_table = $conf['foreign_table'];
             if ($foreign_table) {
@@ -5047,7 +5058,7 @@ class DataHandler implements LoggerAwareInterface
         } elseif ($this->isReferenceField($conf)) {
             $allowedTables = $conf['type'] === 'group' ? $conf['allowed'] : $conf['foreign_table'];
             $dbAnalysis = $this->createRelationHandlerInstance();
-            $dbAnalysis->start($value, $allowedTables, $conf['MM'], $uid, $table, $conf);
+            $dbAnalysis->start($value, $allowedTables, $conf['MM'] ?? '', $uid, $table, $conf);
             foreach ($dbAnalysis->itemArray as $v) {
                 $this->updateRefIndex($v['table'], $v['id']);
             }
@@ -5594,7 +5605,7 @@ class DataHandler implements LoggerAwareInterface
             't3ver_state' => (string)($delete ? new VersionState(VersionState::DELETE_PLACEHOLDER) : new VersionState(VersionState::DEFAULT_STATE)),
             't3ver_stage' => 0,
         ];
-        if ($GLOBALS['TCA'][$table]['ctrl']['editlock']) {
+        if ($GLOBALS['TCA'][$table]['ctrl']['editlock'] ?? false) {
             $overrideArray[$GLOBALS['TCA'][$table]['ctrl']['editlock']] = 0;
         }
         // Checking if the record already has a version in the current workspace of the backend user
@@ -5641,16 +5652,14 @@ class DataHandler implements LoggerAwareInterface
         foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $fConf) {
             $conf = $fConf['config'];
             if ($this->isReferenceField($conf)) {
-                $allowedTables = $conf['type'] === 'group' ? $conf['allowed'] : $conf['foreign_table'];
-                $prependName = $conf['type'] === 'group' ? $conf['prepend_tname'] : '';
-                if ($conf['MM']) {
-                    /** @var RelationHandler $dbAnalysis */
+                $allowedTables = $conf['type'] === 'group' ? ($conf['allowed'] ?? '') : $conf['foreign_table'];
+                $prependName = $conf['type'] === 'group' ? ($conf['prepend_tname'] ?? '') : '';
+                if ($conf['MM'] ?? false) {
                     $dbAnalysis = $this->createRelationHandlerInstance();
                     $dbAnalysis->start('', $allowedTables, $conf['MM'], $id, $table, $conf);
                     if (!empty($dbAnalysis->getValueArray($prependName))) {
                         $this->version_remapMMForVersionSwap_reg[$id][$field] = [$dbAnalysis, $conf['MM'], $prependName];
                     }
-                    /** @var RelationHandler $dbAnalysis */
                     $dbAnalysis = $this->createRelationHandlerInstance();
                     $dbAnalysis->start('', $allowedTables, $conf['MM'], $swapWith, $table, $conf);
                     if (!empty($dbAnalysis->getValueArray($prependName))) {
@@ -5882,16 +5891,16 @@ class DataHandler implements LoggerAwareInterface
         // Allowed tables for references.
         $allowedTables = $conf['type'] === 'group' ? $conf['allowed'] : $conf['foreign_table'];
         // Table name to prepend the UID
-        $prependName = $conf['type'] === 'group' ? $conf['prepend_tname'] : '';
+        $prependName = $conf['type'] === 'group' ? ($conf['prepend_tname'] ?? '') : '';
         // Which tables that should possibly not be remapped
-        $dontRemapTables = GeneralUtility::trimExplode(',', $conf['dontRemapTablesOnCopy'], true);
+        $dontRemapTables = GeneralUtility::trimExplode(',', $conf['dontRemapTablesOnCopy'] ?? '', true);
         // Convert value to list of references:
         $dbAnalysis = $this->createRelationHandlerInstance();
-        $dbAnalysis->registerNonTableValues = $conf['type'] === 'select' && $conf['allowNonIdValues'];
-        $dbAnalysis->start($value, $allowedTables, $conf['MM'], $MM_localUid, $table, $conf);
+        $dbAnalysis->registerNonTableValues = $conf['type'] === 'select' && ($conf['allowNonIdValues'] ?? false);
+        $dbAnalysis->start($value, $allowedTables, $conf['MM'] ?? '', $MM_localUid, $table, $conf);
         // Traverse those references and map IDs:
         foreach ($dbAnalysis->itemArray as $k => $v) {
-            $mapID = $this->copyMappingArray_merged[$v['table']][$v['id']];
+            $mapID = $this->copyMappingArray_merged[$v['table']][$v['id']] ?? 0;
             if ($mapID && !in_array($v['table'], $dontRemapTables, true)) {
                 $dbAnalysis->itemArray[$k]['id'] = $mapID;
                 $set = true;
@@ -5923,7 +5932,7 @@ class DataHandler implements LoggerAwareInterface
         }
         // If a change has been done, set the new value(s)
         if ($set) {
-            if ($conf['MM']) {
+            if ($conf['MM'] ?? false) {
                 $dbAnalysis->writeMM($conf['MM'], $MM_localUid, $prependName);
             } else {
                 return $dbAnalysis->getValueArray($prependName);
@@ -6225,28 +6234,32 @@ class DataHandler implements LoggerAwareInterface
      * @param array $registerDBList Reference to the $registerDBList array that was created/updated by versionizing calls to DataHandler in process_datamap.
      * @internal should only be used from within DataHandler
      */
-    public function getVersionizedIncomingFieldArray($table, $id, &$incomingFieldArray, &$registerDBList)
-    {
-        if (is_array($registerDBList[$table][$id])) {
-            foreach ($incomingFieldArray as $field => $value) {
-                $fieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
-                if ($registerDBList[$table][$id][$field] && ($foreignTable = $fieldConf['foreign_table'])) {
-                    $newValueArray = [];
-                    $origValueArray = is_array($value) ? $value : explode(',', $value);
-                    // Update the uids of the copied records, but also take care about new records:
-                    foreach ($origValueArray as $childId) {
-                        $newValueArray[] = $this->autoVersionIdMap[$foreignTable][$childId] ?: $childId;
-                    }
-                    // Set the changed value to the $incomingFieldArray
-                    $incomingFieldArray[$field] = implode(',', $newValueArray);
+    public function getVersionizedIncomingFieldArray($table, $id, &$incomingFieldArray, &$registerDBList): void
+    {
+        if (!isset($registerDBList[$table][$id]) || !is_array($registerDBList[$table][$id])) {
+            return;
+        }
+        foreach ($incomingFieldArray as $field => $value) {
+            $fieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
+            $foreignTable = $fieldConf['foreign_table'] ?? '';
+            if (($registerDBList[$table][$id][$field] ?? false)
+                && !empty($foreignTable)
+            ) {
+                $newValueArray = [];
+                $origValueArray = is_array($value) ? $value : explode(',', $value);
+                // Update the uids of the copied records, but also take care about new records:
+                foreach ($origValueArray as $childId) {
+                    $newValueArray[] = $this->autoVersionIdMap[$foreignTable][$childId] ?? $childId;
                 }
-            }
-            // Clean up the $registerDBList array:
-            unset($registerDBList[$table][$id]);
-            if (empty($registerDBList[$table])) {
-                unset($registerDBList[$table]);
+                // Set the changed value to the $incomingFieldArray
+                $incomingFieldArray[$field] = implode(',', $newValueArray);
             }
         }
+        // Clean up the $registerDBList array:
+        unset($registerDBList[$table][$id]);
+        if (empty($registerDBList[$table])) {
+            unset($registerDBList[$table]);
+        }
     }
 
     /**
@@ -6853,12 +6866,12 @@ class DataHandler implements LoggerAwareInterface
     public function getRecordPropertiesFromRow($table, $row)
     {
         if ($GLOBALS['TCA'][$table]) {
-            $liveUid = ($row['t3ver_oid'] ?? null) ? $row['t3ver_oid'] : $row['uid'];
+            $liveUid = ($row['t3ver_oid'] ?? null) ? ($row['t3ver_oid'] ?? null) : ($row['uid'] ?? null);
             return [
                 'header' => BackendUtility::getRecordTitle($table, $row),
-                'pid' => $row['pid'],
-                'event_pid' => $this->eventPid($table, (int)$liveUid, $row['pid']),
-                't3ver_state' => BackendUtility::isTableWorkspaceEnabled($table) ? $row['t3ver_state'] : ''
+                'pid' => $row['pid'] ?? null,
+                'event_pid' => $this->eventPid($table, (int)$liveUid, $row['pid'] ?? null),
+                't3ver_state' => BackendUtility::isTableWorkspaceEnabled($table) ? ($row['t3ver_state'] ?? '') : ''
             ];
         }
         return null;
@@ -7477,7 +7490,7 @@ class DataHandler implements LoggerAwareInterface
                 // If there is an element, find its localized record in specified localization language
                 if ($previousRow = $queryBuilder->execute()->fetch()) {
                     $previousLocalizedRecord = BackendUtility::getRecordLocalization($table, $previousRow['uid'], $language);
-                    if (is_array($previousLocalizedRecord[0])) {
+                    if (isset($previousLocalizedRecord[0]) && is_array($previousLocalizedRecord[0])) {
                         $previousLocalizedRecordUid = $previousLocalizedRecord[0]['uid'];
                     }
                 }
@@ -7591,7 +7604,7 @@ class DataHandler implements LoggerAwareInterface
             }
             // Unset the fields which are similar:
             foreach ($fieldArray as $col => $val) {
-                $fieldConfiguration = $GLOBALS['TCA'][$table]['columns'][$col]['config'];
+                $fieldConfiguration = $GLOBALS['TCA'][$table]['columns'][$col]['config'] ?? [];
                 $isNullField = (!empty($fieldConfiguration['eval']) && GeneralUtility::inList($fieldConfiguration['eval'], 'null'));
 
                 // Unset fields if stored and submitted values are equal - except the current field holds MM relations.
@@ -7740,8 +7753,8 @@ class DataHandler implements LoggerAwareInterface
      */
     public function getTableEntries($table, $TSconfig)
     {
-        $tA = is_array($TSconfig['table.'][$table . '.']) ? $TSconfig['table.'][$table . '.'] : [];
-        $dA = is_array($TSconfig['default.']) ? $TSconfig['default.'] : [];
+        $tA = is_array($TSconfig['table.'][$table . '.'] ?? false) ? $TSconfig['table.'][$table . '.'] : [];
+        $dA = is_array($TSconfig['default.'] ?? false) ? $TSconfig['default.'] : [];
         ArrayUtility::mergeRecursiveWithOverrule($dA, $tA);
         return $dA;
     }
@@ -7879,7 +7892,7 @@ class DataHandler implements LoggerAwareInterface
         $newData = [];
         foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $conf) {
             if ($conf['config']['type'] === 'input' && (string)$curData[$field] !== '') {
-                $evalCodesArray = GeneralUtility::trimExplode(',', $conf['config']['eval'], true);
+                $evalCodesArray = GeneralUtility::trimExplode(',', $conf['config']['eval'] ?? '', true);
                 if (in_array('uniqueInPid', $evalCodesArray, true)) {
                     $newV = $this->getUnique($table, $field, $curData[$field], $uid, $curData['pid']);
                     if ((string)$newV !== (string)$curData[$field]) {
@@ -7958,7 +7971,7 @@ class DataHandler implements LoggerAwareInterface
      */
     public function fixCopyAfterDuplFields($table, $uid, $prevUid, $update, $newData = [])
     {
-        if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields']) {
+        if ($GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'] ?? false) {
             $prevData = $this->recordInfo($table, $prevUid, '*');
             $theFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'], true);
             foreach ($theFields as $field) {
@@ -8011,8 +8024,8 @@ class DataHandler implements LoggerAwareInterface
      */
     public function isReferenceField($conf)
     {
-        return $conf['type'] === 'group' && $conf['internal_type'] === 'db'
-            || $conf['type'] === 'select' && ($conf['foreign_table'] ?? false);
+        return isset($conf['type'], $conf['internal_type']) && $conf['type'] === 'group' && $conf['internal_type'] === 'db'
+            || isset($conf['type'], $conf['foreign_table']) && $conf['type'] === 'select' && $conf['foreign_table'];
     }
 
     /**
@@ -8025,7 +8038,7 @@ class DataHandler implements LoggerAwareInterface
      */
     public function getInlineFieldType($conf)
     {
-        if ($conf['type'] !== 'inline' || !$conf['foreign_table']) {
+        if (empty($conf['type']) || $conf['type'] !== 'inline' || empty($conf['foreign_table'])) {
             return false;
         }
         if ($conf['foreign_field'] ?? false) {
@@ -8213,7 +8226,7 @@ class DataHandler implements LoggerAwareInterface
         }
         static::$recordsToClearCacheFor[$table][] = (int)$uid;
         if ($pid !== null) {
-            if (!is_array(static::$recordPidsForDeletedRecords[$table])) {
+            if (!isset(static::$recordPidsForDeletedRecords[$table]) || !is_array(static::$recordPidsForDeletedRecords[$table])) {
                 static::$recordPidsForDeletedRecords[$table] = [];
             }
             static::$recordPidsForDeletedRecords[$table][$uid][] = (int)$pid;
@@ -8614,7 +8627,7 @@ class DataHandler implements LoggerAwareInterface
     {
         $localizationParentFieldName = $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'];
         $row = $this->recordInfo('pages', $pageId, $localizationParentFieldName);
-        $localizationParent = (int)$row[$localizationParentFieldName];
+        $localizationParent = (int)($row[$localizationParentFieldName] ?? 0);
         if ($localizationParent > 0) {
             return $localizationParent;
         }
@@ -8636,6 +8649,7 @@ class DataHandler implements LoggerAwareInterface
         $result = $fieldArray;
         foreach ($fieldArray as $field => $value) {
             if (!MathUtility::canBeInterpretedAsInteger($value)
+                && isset($GLOBALS['TCA'][$table]['columns'][$field]['config']['type'])
                 && $GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'inline'
                 && ($GLOBALS['TCA'][$table]['columns'][$field]['config']['foreign_field'] ?? false)
             ) {
diff --git a/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php b/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php
index 7e605a63761a32e8334a7cf28153ece302fba99b..bcdae62281fbbe286dde1d33194f87a664b2a290 100644
--- a/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php
+++ b/typo3/sysext/core/Classes/DataHandling/ItemProcessingService.php
@@ -41,12 +41,12 @@ class ItemProcessingService
     {
         $pageId = $table === 'pages' ? $row['uid'] : $row['pid'];
         $TSconfig = BackendUtility::getPagesTSconfig($pageId);
-        $fieldTSconfig = $TSconfig['TCEFORM.'][$table . '.'][$field . '.'];
+        $fieldTSconfig = $TSconfig['TCEFORM.'][$table . '.'][$field . '.'] ?? [];
 
         $params = [];
         $params['items'] = &$selectedItems;
         $params['config'] = $tcaConfig;
-        $params['TSconfig'] = $fieldTSconfig['itemsProcFunc.'];
+        $params['TSconfig'] = $fieldTSconfig['itemsProcFunc.'] ?? null;
         $params['table'] = $table;
         $params['row'] = $row;
         $params['field'] = $field;
diff --git a/typo3/sysext/core/Classes/Database/RelationHandler.php b/typo3/sysext/core/Classes/Database/RelationHandler.php
index 9799bac6038dedfa182730fd19c12d3a4016a2f4..23fe1aca33a0fd7285d7453e1349152afa609884 100644
--- a/typo3/sysext/core/Classes/Database/RelationHandler.php
+++ b/typo3/sysext/core/Classes/Database/RelationHandler.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Core\Database;
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Database\Platform\PlatformInformation;
 use TYPO3\CMS\Core\Database\Query\QueryHelper;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
@@ -201,8 +202,9 @@ class RelationHandler
      */
     protected function getWorkspaceId(): int
     {
+        $backendUser = $GLOBALS['BE_USER'] ?? null;
         if (!isset($this->workspaceId)) {
-            $this->workspaceId = (int)$GLOBALS['BE_USER']->workspace;
+            $this->workspaceId = $backendUser instanceof BackendUserAuthentication ? (int)($backendUser->workspace) : 0;
         }
         return $this->workspaceId;
     }
diff --git a/typo3/sysext/core/Classes/Utility/RootlineUtility.php b/typo3/sysext/core/Classes/Utility/RootlineUtility.php
index 9a9be05ad32ee43b02c087bf46da5720e06afb49..1898d9a5cde8605f04d4c8ea0574b26677ac21a9 100644
--- a/typo3/sysext/core/Classes/Utility/RootlineUtility.php
+++ b/typo3/sysext/core/Classes/Utility/RootlineUtility.php
@@ -492,7 +492,7 @@ class RootlineUtility
         }
 
         $page = $this->resolvePageRecord($pageId);
-        if (!VersionState::cast($page['t3ver_state'])->equals(VersionState::MOVE_POINTER)) {
+        if (!isset($page['t3ver_state']) || !VersionState::cast($page['t3ver_state'])->equals(VersionState::MOVE_POINTER)) {
             return $pageId;
         }
 
diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/ContentContentObject.php
index 904ad04a9c97e1d7373941a6b86054b53a7cd9d9..04340bcf532d59a3a865569e30cfa2a11754fe63 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/ContentContentObject.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/ContentContentObject.php
@@ -42,7 +42,11 @@ class ContentContentObject extends AbstractContentObject
         // If the currentRecord is set, we register, that this record has invoked this function.
         // It should not be allowed to do this again then!!
         if ($originalRec) {
-            ++$frontendController->recordRegister[$originalRec];
+            if (isset($frontendController->recordRegister[$originalRec])) {
+                ++$frontendController->recordRegister[$originalRec];
+            } else {
+                $frontendController->recordRegister[$originalRec] = 1;
+            }
         }
         $conf['table'] = trim((string)$this->cObj->stdWrapValue('table', $conf ?? []));
         $conf['select.'] = !empty($conf['select.']) ? $conf['select.'] : [];
@@ -83,10 +87,11 @@ class ContentContentObject extends AbstractContentObject
                         $_procObj = GeneralUtility::makeInstance($className);
                         $_procObj->modifyDBRow($row, $conf['table']);
                     }
-                    if (!$frontendController->recordRegister[$conf['table'] . ':' . $row['uid']]) {
+                    $registerField = $conf['table'] . ':' . $row['uid'];
+                    if (!($frontendController->recordRegister[$registerField] ?? false)) {
                         $this->cObj->currentRecordNumber++;
                         $cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
-                        $frontendController->currentRecord = $conf['table'] . ':' . $row['uid'];
+                        $frontendController->currentRecord = $registerField;
                         $this->cObj->lastChanged($row['tstamp']);
                         $cObj->start($row, $conf['table'], $this->request);
                         $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
index 833dd4ca49bf3c1ff74dff3843504aeb33441b0e..9c24a3a85eaba76ed2260433a1c6969f1cca5430 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
@@ -455,7 +455,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
     public function __construct(TypoScriptFrontendController $typoScriptFrontendController = null, ContainerInterface $container = null)
     {
         $this->typoScriptFrontendController = $typoScriptFrontendController;
-        $this->contentObjectClassMap = $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'];
+        $this->contentObjectClassMap = $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] ?? [];
         $this->container = $container;
     }
 
@@ -4504,13 +4504,13 @@ class ContentObjectRenderer implements LoggerAwareInterface
         $keys = explode('|', $keyString);
         $numberOfLevels = count($keys);
         $rootKey = trim($keys[0]);
-        $value = isset($source) ? $source[$rootKey] : $GLOBALS[$rootKey];
+        $value = isset($source) ? ($source[$rootKey] ?? '') : ($GLOBALS[$rootKey] ?? '');
         for ($i = 1; $i < $numberOfLevels && isset($value); $i++) {
             $currentKey = trim($keys[$i]);
             if (is_object($value)) {
                 $value = $value->{$currentKey};
             } elseif (is_array($value)) {
-                $value = $value[$currentKey];
+                $value = $value[$currentKey] ?? '';
             } else {
                 $value = '';
                 break;
@@ -5742,8 +5742,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
         foreach ($properties as $property) {
             $conf[$property] = trim(
                 isset($conf[$property . '.'])
-                    ? $this->stdWrap($conf[$property], $conf[$property . '.'])
-                    : $conf[$property]
+                    ? $this->stdWrap($conf[$property] ?? '', $conf[$property . '.'] ?? [])
+                    : ($conf[$property] ?? null)
             );
             if ($conf[$property] === '') {
                 unset($conf[$property]);
@@ -5804,7 +5804,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
                 $conf['pidInList'] = implode(',', $expandedPidList);
             }
         }
-        if ((string)$conf['pidInList'] === '') {
+        if ((string)($conf['pidInList'] ?? '') === '') {
             $conf['pidInList'] = 'this';
         }
 
@@ -5816,28 +5816,28 @@ class ContentObjectRenderer implements LoggerAwareInterface
         $queryBuilder->getRestrictions()->removeAll();
         $queryBuilder->select('*')->from($table);
 
-        if ($queryParts['where']) {
+        if ($queryParts['where'] ?? false) {
             $queryBuilder->where($queryParts['where']);
         }
 
-        if ($queryParts['groupBy']) {
+        if ($queryParts['groupBy'] ?? false) {
             $queryBuilder->groupBy(...$queryParts['groupBy']);
         }
 
-        if (is_array($queryParts['orderBy'])) {
+        if (is_array($queryParts['orderBy'] ?? false)) {
             foreach ($queryParts['orderBy'] as $orderBy) {
                 $queryBuilder->addOrderBy(...$orderBy);
             }
         }
 
         // Fields:
-        if ($conf['selectFields']) {
+        if ($conf['selectFields'] ?? false) {
             $queryBuilder->selectLiteral($this->sanitizeSelectPart($conf['selectFields'], $table));
         }
 
         // Setting LIMIT:
         $error = false;
-        if ($conf['max'] || $conf['begin']) {
+        if (($conf['max'] ?? false) || ($conf['begin'] ?? false)) {
             // Finding the total number of records, if used:
             if (strpos(strtolower($conf['begin'] . $conf['max']), 'total') !== false) {
                 $countQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
@@ -5872,7 +5872,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
 
         if (!$error) {
             // Setting up tablejoins:
-            if ($conf['join']) {
+            if ($conf['join'] ?? false) {
                 $joinParts = QueryHelper::parseJoin($conf['join']);
                 $queryBuilder->join(
                     $table,
@@ -5880,7 +5880,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
                     $joinParts['tableAlias'],
                     $joinParts['joinCondition']
                 );
-            } elseif ($conf['leftjoin']) {
+            } elseif ($conf['leftjoin'] ?? false) {
                 $joinParts = QueryHelper::parseJoin($conf['leftjoin']);
                 $queryBuilder->leftJoin(
                     $table,
@@ -5888,7 +5888,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
                     $joinParts['tableAlias'],
                     $joinParts['joinCondition']
                 );
-            } elseif ($conf['rightjoin']) {
+            } elseif ($conf['rightjoin'] ?? false) {
                 $joinParts = QueryHelper::parseJoin($conf['rightjoin']);
                 $queryBuilder->rightJoin(
                     $table,
@@ -6029,7 +6029,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
             && !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
         );
 
-        if (trim($conf['uidInList'])) {
+        if (trim($conf['uidInList'] ?? '')) {
             $listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $conf['uidInList']));
 
             // If moved records shall be considered, select via t3ver_oid
@@ -6172,9 +6172,10 @@ class ContentObjectRenderer implements LoggerAwareInterface
             $languageQuery = $expressionBuilder->in($languageField, [0, -1]);
             // Use this option to include records that don't have a default language counterpart ("free mode")
             // (originalpointerfield is 0 and the language field contains the requested language)
-            if (isset($conf['includeRecordsWithoutDefaultTranslation']) || $conf['includeRecordsWithoutDefaultTranslation.']) {
-                $includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.']) ?
-                    $this->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.']) : $conf['includeRecordsWithoutDefaultTranslation'];
+            if (isset($conf['includeRecordsWithoutDefaultTranslation']) || !empty($conf['includeRecordsWithoutDefaultTranslation.'])) {
+                $includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.'])
+                    ? $this->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.'])
+                    : $conf['includeRecordsWithoutDefaultTranslation'];
                 $includeRecordsWithoutDefaultTranslation = trim($includeRecordsWithoutDefaultTranslation) !== '';
             } else {
                 // Option was not explicitly set, check what's in for the language overlay type.
@@ -6267,7 +6268,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
      */
     public function getQueryMarkers($table, $conf)
     {
-        if (!is_array($conf['markers.'])) {
+        if (!isset($conf['markers.']) || !is_array($conf['markers.'])) {
             return [];
         }
         // Parse markers and prepare their values
diff --git a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
index 1ae6b6eccf165abc4791ae62db3050c9cfdd1329..42d0888d4fd0031b2ba3e97763835e8778df5a11 100644
--- a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
+++ b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
@@ -8063,6 +8063,96 @@ class ContentObjectRendererTest extends UnitTestCase
         );
     }
 
+    public function getGlobalDataProvider(): array
+    {
+        return [
+            'simple' => [
+                'foo',
+                'HTTP_SERVER_VARS | something',
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something' => 'foo',
+                    ]
+                ],
+                null
+            ],
+            'simple source fallback' => [
+                'foo',
+                'HTTP_SERVER_VARS | something',
+                null,
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something' => 'foo',
+                    ]
+                ],
+            ],
+            'globals ignored if source given' => [
+                '',
+                'HTTP_SERVER_VARS | something',
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something' => 'foo',
+                    ]
+                ],
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something-else' => 'foo',
+                    ]
+                ],
+            ],
+            'sub array is returned as empty string' => [
+                '',
+                'HTTP_SERVER_VARS | something',
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something' => [ 'foo' ],
+                    ]
+                ],
+                null
+            ],
+            'does not exist' => [
+                '',
+                'HTTP_SERVER_VARS | something',
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something-else' => 'foo',
+                    ]
+                ],
+                null
+            ],
+            'does not exist in source' => [
+                '',
+                'HTTP_SERVER_VARS | something',
+                null,
+                [
+                    'HTTP_SERVER_VARS' => [
+                        'something-else' => 'foo',
+                    ]
+                ]
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider getGlobalDataProvider
+     * @param mixed $expected
+     * @param string $key
+     * @param array $globals
+     * @param null $source
+     */
+    public function getGlobalReturnsExpectedResult($expected, string $key, ?array $globals, ?array $source): void
+    {
+        if (isset($globals['HTTP_SERVER_VARS'])) {
+            // Note we can't simply $GLOBALS = $globals, since phpunit backupGlobals works on existing array keys.
+            $GLOBALS['HTTP_SERVER_VARS'] = $globals['HTTP_SERVER_VARS'];
+        }
+        self::assertSame(
+            $expected,
+            (new ContentObjectRenderer())->getGlobal($key, $source)
+        );
+    }
+
     /***************************************************************************
      * End: Mixed tests
      ***************************************************************************/
diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
index 680e3ed8d7db825dc2f7329f63bf2b2677b8615d..623696bd48c1b7fab9081dd3a68a984ba78b41e8 100644
--- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
+++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
@@ -1488,7 +1488,7 @@ class DataHandlerHook
         $listArr = [];
         foreach ($GLOBALS['TCA'][$table]['columns'] ?? [] as $field => $configArr) {
             if ($configArr['config']['type'] === 'input') {
-                $evalCodesArray = GeneralUtility::trimExplode(',', $configArr['config']['eval'], true);
+                $evalCodesArray = GeneralUtility::trimExplode(',', $configArr['config']['eval'] ?? '', true);
                 if (in_array('uniqueInPid', $evalCodesArray) || in_array('unique', $evalCodesArray)) {
                     $listArr[] = $field;
                 }
diff --git a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php
index 3e725f808126974efa9ff7c9ed998f688d9c1abf..7ea12131403af39766b871223a69921d334fe2d7 100644
--- a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php
+++ b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php
@@ -839,7 +839,7 @@ class WorkspaceService implements SingletonInterface
     protected function isLanguageAccessibleForCurrentUser($table, array $record)
     {
         if (BackendUtility::isTableLocalizable($table)) {
-            $languageUid = $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
+            $languageUid = $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']] ?? 0;
         } else {
             return true;
         }