Skip to content

Commit 95e001e

Browse files
committed
Fix #79423: copy command is limited to size of file it can copy
Passing `NULL` as `lpFileSizeHigh` to `GetFileSize()` gives wrong results for files larger than 0xFFFFFFFF bytes. We fix this by using `GetFileSizeEx()`, and proceed with `MIN(file_size, SIZE_MAX)`.
1 parent 1848ccd commit 95e001e

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug #79423 (copy command is limited to size of file it can copy)
3+
--SKIPIF--
4+
<?php
5+
if (getenv('SKIP_SLOW_TESTS')) die('skip slow test');
6+
?>
7+
--FILE--
8+
<?php
9+
$orig = __DIR__ . '/bug79423_orig.txt';
10+
$copy = __DIR__ . '/bug79423_copy.txt';
11+
12+
// create file of 0xFFFFFFFF bytes (SIZE_MAX on 32bit systems)
13+
$text = str_repeat('*', 1024 * 1024);
14+
$stream = fopen($orig, 'w');
15+
for ($i = 0; $i < 4095; $i++) {
16+
fwrite($stream, $text);
17+
}
18+
fwrite($stream, $text, strlen($text) - 1);
19+
fclose($stream);
20+
21+
var_dump(copy($orig, $copy));
22+
var_dump(filesize($orig) === filesize($copy));
23+
?>
24+
--CLEAN--
25+
<?php
26+
unlink(__DIR__ . '/bug79423_orig.txt');
27+
unlink(__DIR__ . '/bug79423_copy.txt');
28+
?>
29+
--EXPECT--
30+
bool(true)
31+
bool(true)

main/streams/plain_wrapper.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
749749
php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
750750
HANDLE hfile = (HANDLE)_get_osfhandle(fd);
751751
DWORD prot, acc, loffs = 0, delta = 0;
752+
LARGE_INTEGER file_size;
752753

753754
switch (value) {
754755
case PHP_STREAM_MMAP_SUPPORTED:
@@ -785,7 +786,19 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
785786
return PHP_STREAM_OPTION_RETURN_ERR;
786787
}
787788

788-
size = GetFileSize(hfile, NULL);
789+
if (!GetFileSizeEx(hfile, &file_size)) {
790+
return PHP_STREAM_OPTION_RETURN_ERR;
791+
}
792+
# if defined(_WIN64)
793+
size = file_size.QuadPart;
794+
# else
795+
if (file_size.HighPart) {
796+
/* file is too large; process as much as possible */
797+
size = SIZE_MAX;
798+
} else {
799+
size = file_size.LowPart;
800+
}
801+
# endif
789802
if (range->offset > size) {
790803
range->offset = size;
791804
}

0 commit comments

Comments
 (0)