From 72a7312ce91487256695d6c461e4c4dff52916be Mon Sep 17 00:00:00 2001
From: Alexander Schnitzler <git@alexanderschnitzler.de>
Date: Sat, 30 Jan 2016 14:10:11 +0100
Subject: [PATCH] [BUGFIX] Avoid memory leak during file searches

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/46395
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Daniel Maier <dani-maier@gmx.de>
Tested-by: Daniel Maier <dani-maier@gmx.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 typo3/sysext/core/Classes/Resource/FileRepository.php       | 6 +-----
 .../core/Classes/Resource/Index/FileIndexRepository.php     | 4 +++-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/typo3/sysext/core/Classes/Resource/FileRepository.php b/typo3/sysext/core/Classes/Resource/FileRepository.php
index f8643384ef12..5b9acaddfd27 100644
--- a/typo3/sysext/core/Classes/Resource/FileRepository.php
+++ b/typo3/sysext/core/Classes/Resource/FileRepository.php
@@ -152,14 +152,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 (Exception\FileDoesNotExistException $ignoredException) {
diff --git a/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php b/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
index 67c893f15559..5b9032800f28 100644
--- a/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
+++ b/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
@@ -203,9 +203,10 @@ class FileIndexRepository implements SingletonInterface
      *
      * @param 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 = [];
@@ -226,6 +227,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'),
             '',
             '',
-- 
GitLab