[BUGFIX] Avoid memory leak during file searches 78/47078/2
authorAlexander Schnitzler <git@alexanderschnitzler.de>
Sat, 30 Jan 2016 13:10:11 +0000 (14:10 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Fri, 4 Mar 2016 19:05:56 +0000 (20:05 +0100)
During the file search in the file module the search result
is only limited to possibly matching folders. That itself
decreases the search over all files in a storage but it
still does not prevent memory leaks, where the result
of possible folders contain a decent amount of files.

Example:
fileadmin has a total of 10.000 files.
fileadmin has a subfolder called foo
fileadmin/foo holds a subset of 1000 files.
fileadmin/foo holds the file bar

A search for bar asks the database for all folders that contain
files with the matching identifier bar. As a result, only the
folder fileadmin/foo is returned which already excludes 9000
possible files.

Still, the resultset contains 1000 files, whoose name is
compared php-wise with the search string. During that
foreach loop each a file object with a decent memory
footprint will be created. This easily exceeds the
available memory limit.

Resolves: #73032
Releases: master, 7.6
Change-Id: Icf46e05274c671db344797d207afefc029c5fb5b
Reviewed-on: https://review.typo3.org/47078
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/core/Classes/Resource/FileRepository.php
typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php

index b13f0f7..5be17d6 100644 (file)
@@ -149,14 +149,10 @@ class FileRepository extends AbstractRepository
         $folders = $folder->getStorage()->getFoldersInFolder($folder, 0, 0, true, true);
         $folders[$folder->getIdentifier()] = $folder;
 
-        $fileRecords = $this->getFileIndexRepository()->findByFolders($folders, false);
+        $fileRecords = $this->getFileIndexRepository()->findByFolders($folders, false, $fileName);
 
         $files = array();
         foreach ($fileRecords as $fileRecord) {
-            if (stristr($fileRecord['name'], $fileName) === false) {
-                continue;
-            }
-
             try {
                 $files[] = $fileFactory->getFileObject($fileRecord['uid'], $fileRecord);
             } catch (\TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException $ignoredException) {
index 3d2ad93..7144852 100644 (file)
@@ -197,9 +197,10 @@ class FileIndexRepository implements SingletonInterface
      *
      * @param \TYPO3\CMS\Core\Resource\Folder[] $folders
      * @param bool $includeMissing
+     * @param string $fileName
      * @return array|NULL
      */
-    public function findByFolders(array $folders, $includeMissing = true)
+    public function findByFolders(array $folders, $includeMissing = true, $fileName = null)
     {
         $storageUids = [];
         $folderIdentifiers = [];
@@ -220,6 +221,7 @@ class FileIndexRepository implements SingletonInterface
             $this->table,
             'folder_hash IN ( ' . implode(',', $this->getDatabaseConnection()->fullQuoteArray($folderIdentifiers, $this->table)) . ')' .
             ' AND storage IN (' . implode(',', $storageUids) . ')' .
+            (isset($fileName) ? ' AND name LIKE "%' . $this->getDatabaseConnection()->escapeStrForLike($this->getDatabaseConnection()->quoteStr($fileName, $this->table), $this->table) . '%"' : '') .
             ($includeMissing ? '' : ' AND missing = 0'),
             '',
             '',