From 4000780b3d0bbba2d94f65602e602c3892d9775b Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 9 Sep 2020 19:21:41 +0200 Subject: [PATCH] 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 let the mapping fail, if the file size is too large for the architecture. Closes GH-5319. --- NEWS | 4 ++++ main/streams/plain_wrapper.c | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 98dd5861148..54463d49838 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 7.3.24 +- Core: + . Fixed bug #79423 (copy command is limited to size of file it can copy). + (cmb) + - MySQLnd: . Fixed bug #80115 (mysqlnd.debug doesn't recognize absolute paths with slashes). (cmb) diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 2b819128576..d00a6efe29d 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -749,6 +749,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; HANDLE hfile = (HANDLE)_get_osfhandle(fd); DWORD prot, acc, loffs = 0, delta = 0; + LARGE_INTEGER file_size; switch (value) { case PHP_STREAM_MMAP_SUPPORTED: @@ -785,7 +786,22 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return PHP_STREAM_OPTION_RETURN_ERR; } - size = GetFileSize(hfile, NULL); + if (!GetFileSizeEx(hfile, &file_size)) { + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + return PHP_STREAM_OPTION_RETURN_ERR; + } +# if defined(_WIN64) + size = file_size.QuadPart; +# else + if (file_size.HighPart) { + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + return PHP_STREAM_OPTION_RETURN_ERR; + } else { + size = file_size.LowPart; + } +# endif if (range->offset > size) { range->offset = size; }