Skip to content

Commit 8784f04

Browse files
authored
Merge pull request #29 from biigle/patch-4
Fix maxBytes check
2 parents 7c2cb26 + b34b7ac commit 8784f04

2 files changed

Lines changed: 55 additions & 4 deletions

File tree

src/FileCache.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -575,16 +575,26 @@ protected function cacheFromResource(File $file, $source, $target)
575575

576576
$cachedPath = $this->getCachedPath($file);
577577
$maxBytes = intval($this->config['max_file_size']);
578-
$bytes = stream_copy_to_stream($source, $target, $maxBytes);
579-
580-
if ($bytes === $maxBytes) {
581-
throw new Exception("The file is too large with more than {$maxBytes} bytes.");
578+
// Copy one byte more than allowed to detect files that exceed the limit.
579+
// Using $maxBytes directly would reject files of exactly $maxBytes bytes.
580+
// Clamp at PHP_INT_MAX to avoid overflowing to float for very large limits.
581+
if ($maxBytes < 0) {
582+
$copyLimit = -1;
583+
} elseif ($maxBytes < PHP_INT_MAX) {
584+
$copyLimit = $maxBytes + 1;
585+
} else {
586+
$copyLimit = PHP_INT_MAX;
582587
}
588+
$bytes = stream_copy_to_stream($source, $target, $copyLimit);
583589

584590
if ($bytes === false) {
585591
throw new Exception('The source resource is invalid.');
586592
}
587593

594+
if ($maxBytes >= 0 && $bytes > $maxBytes) {
595+
throw new Exception("The file is too large with more than {$maxBytes} bytes.");
596+
}
597+
588598
$metadata = stream_get_meta_data($source);
589599

590600
if (array_key_exists('timed_out', $metadata) && $metadata['timed_out']) {

tests/FileCacheTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,23 @@ public function testGetRemoteTooLarge()
9595
$this->assertFalse(is_resource($cache->stream));
9696
}
9797

98+
public function testGetRemoteExactlyMaxSize()
99+
{
100+
$file = new GenericFile('https://files/image.jpg');
101+
$cache = new FileCacheStub([
102+
'path' => $this->cachePath,
103+
'max_file_size' => 3,
104+
]);
105+
106+
$stream = fopen('php://temp', 'r+');
107+
fwrite($stream, 'abc');
108+
rewind($stream);
109+
$cache->stream = $stream;
110+
$path = $cache->get($file, $this->noop);
111+
$this->assertEquals(3, filesize($path));
112+
$this->assertFalse(is_resource($cache->stream));
113+
}
114+
98115
public function testGetDiskDoesNotExist()
99116
{
100117
$file = new GenericFile('abc://files/image.jpg');
@@ -180,6 +197,30 @@ public function testGetDiskCloudTooLarge()
180197
$this->assertFalse(is_resource($stream));
181198
}
182199

200+
public function testGetDiskCloudExactlyMaxSize()
201+
{
202+
config(['filesystems.disks.s3' => ['driver' => 's3']]);
203+
$file = new GenericFile('s3://files/image.txt');
204+
205+
$stream = fopen('php://temp', 'r+');
206+
fwrite($stream, 'abc');
207+
rewind($stream);
208+
209+
$mock = Mockery::mock();
210+
$mock->shouldReceive('disk')->once()->with('s3')->andReturn($mock);
211+
$mock->shouldReceive('readStream')->once()->andReturn($stream);
212+
$this->app['filesystem'] = $mock;
213+
214+
$cache = new FileCache([
215+
'path' => $this->cachePath,
216+
'max_file_size' => 3,
217+
]);
218+
219+
$path = $cache->get($file, $this->noop);
220+
$this->assertEquals(3, filesize($path));
221+
$this->assertFalse(is_resource($stream));
222+
}
223+
183224
public function testGetThrowOnLock()
184225
{
185226
$cache = new FileCache(['path' => $this->cachePath]);

0 commit comments

Comments
 (0)