diff --git a/ext/standard/tests/file/bug81145.phpt b/ext/standard/tests/file/bug81145.phpt new file mode 100644 index 0000000000000..2f12d9eee81da --- /dev/null +++ b/ext/standard/tests/file/bug81145.phpt @@ -0,0 +1,48 @@ +--TEST-- +Bug #81145 (copy() and stream_copy_to_stream() fail for +4GB files) +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECT-- +Identical diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index d187c23a59316..4d10e688b5f76 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -770,7 +770,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; + DWORD prot, acc, loffs = 0, hoffs = 0, delta = 0; LARGE_INTEGER file_size; switch (value) { @@ -838,8 +838,11 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void GetSystemInfo(&info); gran = info.dwAllocationGranularity; - loffs = ((DWORD)range->offset / gran) * gran; - delta = (DWORD)range->offset - loffs; + ZEND_ASSERT(gran != 0 && (gran & (gran - 1)) == 0); + size_t rounded_offset = (range->offset / gran) * gran; + delta = range->offset - rounded_offset; + loffs = (DWORD)rounded_offset; + hoffs = (DWORD)(rounded_offset >> 32); } /* MapViewOfFile()ing zero bytes would map to the end of the file; match *nix behavior instead */ @@ -847,7 +850,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return PHP_STREAM_OPTION_RETURN_ERR; } - data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta); + data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, hoffs, loffs, range->length + delta); if (data->last_mapped_addr) { /* give them back the address of the start offset they requested */