Skip to content

Commit 6fa2493

Browse files
committed
Merge branch 'PHP-7.4' into master
* PHP-7.4: Fix mmap copying
2 parents e95fa3e + 19c8445 commit 6fa2493

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

main/streams/php_stream_mmap.h

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ typedef struct {
5656

5757
#define PHP_STREAM_MMAP_ALL 0
5858

59+
#define PHP_STREAM_MMAP_MAX (512 * 1024 * 1024)
60+
5961
#define php_stream_mmap_supported(stream) (_php_stream_set_option((stream), PHP_STREAM_OPTION_MMAP_API, PHP_STREAM_MMAP_SUPPORTED, NULL) == 0 ? 1 : 0)
6062

6163
/* Returns 1 if the stream in its current state can be memory mapped,

main/streams/plain_wrapper.c

+5
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,11 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
829829
delta = (DWORD)range->offset - loffs;
830830
}
831831

832+
/* MapViewOfFile()ing zero bytes would map to the end of the file; match *nix behavior instead */
833+
if (range->length + delta == 0) {
834+
return PHP_STREAM_OPTION_RETURN_ERR;
835+
}
836+
832837
data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta);
833838

834839
if (data->last_mapped_addr) {

main/streams/streams.c

+36-17
Original file line numberDiff line numberDiff line change
@@ -1566,29 +1566,48 @@ PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size
15661566

15671567
if (php_stream_mmap_possible(src)) {
15681568
char *p;
1569-
size_t mapped;
15701569

1571-
p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
1570+
do {
1571+
size_t chunk_size = (maxlen == 0 || maxlen > PHP_STREAM_MMAP_MAX) ? PHP_STREAM_MMAP_MAX : maxlen;
1572+
size_t mapped;
15721573

1573-
if (p) {
1574-
ssize_t didwrite = php_stream_write(dest, p, mapped);
1575-
if (didwrite < 0) {
1576-
*len = 0;
1577-
return FAILURE;
1578-
}
1574+
p = php_stream_mmap_range(src, php_stream_tell(src), chunk_size, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
1575+
1576+
if (p) {
1577+
ssize_t didwrite;
1578+
1579+
if (php_stream_seek(src, mapped, SEEK_CUR) != 0) {
1580+
php_stream_mmap_unmap(src);
1581+
break;
1582+
}
1583+
1584+
didwrite = php_stream_write(dest, p, mapped);
1585+
if (didwrite < 0) {
1586+
*len = haveread;
1587+
return FAILURE;
1588+
}
15791589

1580-
php_stream_mmap_unmap_ex(src, mapped);
1590+
php_stream_mmap_unmap(src);
15811591

1582-
*len = didwrite;
1592+
*len = haveread += didwrite;
15831593

1584-
/* we've got at least 1 byte to read
1585-
* less than 1 is an error
1586-
* AND read bytes match written */
1587-
if (mapped > 0 && mapped == didwrite) {
1588-
return SUCCESS;
1594+
/* we've got at least 1 byte to read
1595+
* less than 1 is an error
1596+
* AND read bytes match written */
1597+
if (mapped == 0 || mapped != didwrite) {
1598+
return FAILURE;
1599+
}
1600+
if (mapped < chunk_size) {
1601+
return SUCCESS;
1602+
}
1603+
if (maxlen != 0) {
1604+
maxlen -= mapped;
1605+
if (maxlen == 0) {
1606+
return SUCCESS;
1607+
}
1608+
}
15891609
}
1590-
return FAILURE;
1591-
}
1610+
} while (p);
15921611
}
15931612

15941613
while(1) {

0 commit comments

Comments
 (0)