Description
Symfony version(s) affected: 2.0 till master (The FileBag.php has not changed for a long time on that part)
Description
The repeated use of new FileBag($_FILES) might result in a FileNotFoundException. This has been a problem on one of our customers installations when changing from Shopware 5.5.10 to 5.6.6 due to its different handling of requests with cache active. This might be a Shopware specific handling error, but the provided solution seems small enough to prevent more problems than it might create.
How to reproduce
- Create an file upload field on a form.
- Upload any file on the form. Have the handling action do the following three things during the same PHP call.
- Use new FileBag($_FILES) to parse the files.
- Move the resulting UploadedFile object using the "move" method.
- Use new FileBag($_FILES) again.
On a Shopware 5.6.6 frontend this happens with HTTP Cache activated on custom controllers and methods as the cache does a second run through the code after the first one finished (and possibly moved some uploaded files).
Possible Solution
On "FileBag.php" the "$file = new UploadFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);" line should be replaced with a code like this:
$key = $file['tmp_name'];
static $processedFiles;
if ( !isset($processedFiles) ) {
$processedFiles = [];
}
if ( isset($processedFiles[$key]) ) {
$file = $processedFiles[$key];
} else {
$file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
$processedFiles[$key] = $file;
}
If you want to keep it backwards (PHP 5.6 or lower) compatible, the static variable could be put into the class context as a private variable. This change creates a static cache for "UploadedFile" objects to keep the same UploadedFile instances available with multiple instances of FileBag. Since the "move_uploaded_file" happens somewhere in the code, the second call would not find the file any more.
Additional Concerns
If you are concerned about performance (memory leaks on large upload forms), you could add a static flag to not use this cache. This should however not pose a problem as the objects don't store the content but just some meta data.