[BUGFIX] Prevent infinite loop in FAL access check 09/39109/3
authorNicole Cordes <typo3@cordes.co>
Thu, 30 Apr 2015 16:32:20 +0000 (18:32 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Sun, 3 May 2015 14:56:34 +0000 (16:56 +0200)
If you have a storage which defines the processed folder in another
storage an infinite loop occurs when accessing the file list as
non-admin user. This is because the function getProcessingFolders
is called within the access check and starts access check for the
processed folder as well. This patch creates folder objects without
any access check (because processed folders should be readable and
writeable for everyone). Furthermore the processed folders for a storage
are cached after first fetch.

Releases: master, 6.2
Resolves: #66695
Change-Id: I9dade448466160f8c66f6118622d074f52bff702
Reviewed-on: http://review.typo3.org/39109
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Frans Saris <franssaris@gmail.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Frans Saris <franssaris@gmail.com>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/core/Classes/Resource/ResourceStorage.php

index acbf72c..5608581 100644 (file)
@@ -126,6 +126,13 @@ class ResourceStorage implements ResourceStorageInterface {
        protected $processingFolder;
 
        /**
+        * All processing folders of this storage used in any storage
+        *
+        * @var Folder[]
+        */
+       protected $processingFolders;
+
+       /**
         * whether this storage is online or offline in this request
         *
         * @var bool
@@ -1394,17 +1401,27 @@ class ResourceStorage implements ResourceStorageInterface {
         * @return Folder[]
         */
        public function getProcessingFolders() {
-               $processingFolders = array();
-
-               /** @var $storageRepository StorageRepository */
-               $storageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\StorageRepository::class);
-               $allStorages = $storageRepository->findAll();
-               foreach ($allStorages as $storage) {
-                       if ($storage->getProcessingFolder()->getStorage() === $this) {
-                               $processingFolders[] = $storage->getProcessingFolder();
+               if ($this->processingFolders === NULL) {
+                       $this->processingFolders = array();
+                       $this->processingFolders[] = $this->getProcessingFolder();
+                       /** @var $storageRepository StorageRepository */
+                       $storageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\StorageRepository::class);
+                       $allStorages = $storageRepository->findAll();
+                       foreach ($allStorages as $storage) {
+                               // To circumvent the permission check of the folder, we use the factory to create it "manually" instead of directly using $storage->getProcessingFolder()
+                               // See #66695 for details
+                               list($storageUid, $processingFolderIdentifier) = GeneralUtility::trimExplode(':', $storage->getStorageRecord()['processingfolder']);
+                               if (empty($processingFolderIdentifier) || (int)$storageUid !== $this->getUid()) {
+                                       continue;
+                               }
+                               $potentialProcessingFolder = ResourceFactory::getInstance()->getInstance()->createFolderObject($this, $processingFolderIdentifier, $processingFolderIdentifier);
+                               if ($potentialProcessingFolder->getStorage() === $this && $potentialProcessingFolder->getIdentifier() !== $this->getProcessingFolder()->getIdentifier()) {
+                                       $this->processingFolders[] = $potentialProcessingFolder;
+                               }
                        }
                }
-               return $processingFolders;
+
+               return $this->processingFolders;
        }
 
        /**