Skip to content

Commit 27d216b

Browse files
committed
fix: UploadedFile::hasMoved() may return incorrect value
1 parent 03f5195 commit 27d216b

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

system/HTTP/Files/UploadedFile.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,25 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite =
141141
$destination = $overwrite ? $targetPath . $name : $this->getDestination($targetPath . $name);
142142

143143
try {
144-
move_uploaded_file($this->path, $destination);
144+
$this->hasMoved = move_uploaded_file($this->path, $destination);
145145
} catch (Exception $e) {
146146
$error = error_get_last();
147147
$message = isset($error['message']) ? strip_tags($error['message']) : '';
148148

149149
throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message);
150150
}
151151

152+
if ($this->hasMoved === false) {
153+
$message = 'move_uploaded_file() returned false';
154+
155+
throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message);
156+
}
157+
152158
@chmod($targetPath, 0777 & ~umask());
153159

154160
// Success, so store our new information
155-
$this->path = $targetPath;
156-
$this->name = basename($destination);
157-
$this->hasMoved = true;
161+
$this->path = $targetPath;
162+
$this->name = basename($destination);
158163

159164
return true;
160165
}

tests/system/HTTP/Files/FileMovingTest.php

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ protected function setUp(): void
3535
}
3636

3737
$_FILES = [];
38+
39+
// Set the mock's return value to true
40+
move_uploaded_file('', '', true);
3841
}
3942

4043
protected function tearDown(): void
@@ -262,7 +265,7 @@ public function testInvalidFile()
262265
$file->move($destination, $file->getName(), false);
263266
}
264267

265-
public function testFailedMove()
268+
public function testFailedMoveBecauseOfWarning()
266269
{
267270
$_FILES = [
268271
'userfile' => [
@@ -287,6 +290,41 @@ public function testFailedMove()
287290
$this->expectException(HTTPException::class);
288291
$file->move($destination, $file->getName(), false);
289292
}
293+
294+
public function testFailedMoveBecauseOfFalseReturned()
295+
{
296+
$finalFilename = 'fileA';
297+
298+
$_FILES = [
299+
'userfile1' => [
300+
'name' => $finalFilename . '.txt',
301+
'type' => 'text/plain',
302+
'size' => 124,
303+
'tmp_name' => '/tmp/fileA.txt',
304+
'error' => 0,
305+
],
306+
];
307+
308+
$collection = new FileCollection();
309+
310+
$this->assertTrue($collection->hasFile('userfile1'));
311+
312+
$destination = $this->destination;
313+
314+
// Create the destination if not exists
315+
if (! is_dir($destination)) {
316+
mkdir($destination, 0777, true);
317+
}
318+
319+
$file = $collection->getFile('userfile1');
320+
321+
// Set the mock's return value to false
322+
move_uploaded_file('', '', false);
323+
324+
$this->expectException(HTTPException::class);
325+
326+
$file->move($destination, $file->getName(), false);
327+
}
290328
}
291329

292330
/*
@@ -311,10 +349,20 @@ function is_uploaded_file($filename)
311349
* This overwrite is for testing the move operation.
312350
*/
313351

314-
function move_uploaded_file($filename, $destination)
352+
function move_uploaded_file($filename, $destination, ?bool $setReturnValue = null)
315353
{
354+
static $return = true;
355+
356+
if ($setReturnValue !== null) {
357+
$return = $setReturnValue;
358+
359+
return true;
360+
}
361+
316362
copy($filename, $destination);
317363
unlink($filename);
364+
365+
return $return;
318366
}
319367

320368
function rrmdir($src)

0 commit comments

Comments
 (0)