php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #27792
Patch php551LFS.patch revision 2013-08-30 14:07 UTC by mail dot pourri at laposte dot net

Patch php551LFS.patch for Filesystem function related Bug #27792

Patch version 2013-08-30 14:07 UTC

Return to Bug #27792 | Download this patch
Patch Revisions:

Developer: mail.pourri@laposte.net

diff -ur php-5.5.1/ext/phar/phar_internal.h php-5.5.1.new/ext/phar/phar_internal.h
--- php-5.5.1/ext/phar/phar_internal.h	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/ext/phar/phar_internal.h	2013-08-15 10:42:39.332887601 +0200
@@ -534,8 +534,15 @@
 	return FAILURE;
 }
 #else
-# define phar_stream_copy_to_stream(src, dest, maxlen, len)	_php_stream_copy_to_stream_ex((src), (dest), (maxlen), (len) STREAMS_CC TSRMLS_CC)
-
+static inline size_t phar_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, size_t *len)
+{
+	off_t _maxlen = maxlen == (size_t)PHP_STREAM_COPY_ALL ? PHP_STREAM_COPY_ALL : maxlen, _len = 0;
+	size_t ret = php_stream_copy_to_stream_ex(src, dest, _maxlen, &_len);
+	if (ret == SUCCESS) {
+		if (len) *len = (size_t)_len;
+	} else if (len) *len = 0;
+	return ret;
+}
 #endif
 
 #if PHP_VERSION_ID >= 60000
diff -ur php-5.5.1/ext/standard/file.c php-5.5.1.new/ext/standard/file.c
--- php-5.5.1/ext/standard/file.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/ext/standard/file.c	2013-08-15 10:42:39.432888125 +0200
@@ -570,7 +570,7 @@
 	char *filename;
 	int filename_len;
 	zval *data;
-	int numbytes = 0;
+	off_t numbytes = 0;
 	long flags = 0;
 	zval *zcontext = NULL;
 	php_stream_context *context = NULL;
@@ -618,7 +618,7 @@
 
 	switch (Z_TYPE_P(data)) {
 		case IS_RESOURCE: {
-			size_t len;
+			off_t len;
 			if (php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL, &len) != SUCCESS) {
 				numbytes = -1;
 			} else {
@@ -635,9 +635,9 @@
 
 		case IS_STRING:
 			if (Z_STRLEN_P(data)) {
-				numbytes = php_stream_write(stream, Z_STRVAL_P(data), Z_STRLEN_P(data));
-				if (numbytes != Z_STRLEN_P(data)) {
-					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN_P(data));
+				numbytes = (off_t)php_stream_write(stream, Z_STRVAL_P(data), Z_STRLEN_P(data));
+				if (numbytes != (off_t)Z_STRLEN_P(data)) {
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", (size_t)numbytes, Z_STRLEN_P(data));
 					numbytes = -1;
 				}
 			}
@@ -656,13 +656,13 @@
 						convert_to_string(*tmp);
 					}
 					if (Z_STRLEN_PP(tmp)) {
-						numbytes += Z_STRLEN_PP(tmp);
+						numbytes += (off_t)Z_STRLEN_PP(tmp);
 						bytes_written = php_stream_write(stream, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
 						if (bytes_written < 0 || bytes_written != Z_STRLEN_PP(tmp)) {
 							if (bytes_written < 0) {
 								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d bytes to %s", Z_STRLEN_PP(tmp), filename);
 							} else {
-								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", bytes_written, Z_STRLEN_PP(tmp));
+								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", (size_t)bytes_written, Z_STRLEN_PP(tmp));
 							}
 							numbytes = -1;
 							break;
@@ -678,9 +678,9 @@
 				zval out;
 
 				if (zend_std_cast_object_tostring(data, &out, IS_STRING TSRMLS_CC) == SUCCESS) {
-					numbytes = php_stream_write(stream, Z_STRVAL(out), Z_STRLEN(out));
-					if (numbytes != Z_STRLEN(out)) {
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN(out));
+					numbytes = (off_t)php_stream_write(stream, Z_STRVAL(out), Z_STRLEN(out));
+					if (numbytes != (off_t)Z_STRLEN(out)) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", (size_t)numbytes, Z_STRLEN(out));
 						numbytes = -1;
 					}
 					zval_dtor(&out);
@@ -697,7 +697,11 @@
 		RETURN_FALSE;
 	}
 
-	RETURN_LONG(numbytes);
+        if (numbytes > LONG_MAX) {
+		RETURN_DOUBLE((double)numbytes);
+	} else {
+		RETURN_LONG(numbytes);
+	}
 }
 /* }}} */
 
@@ -1245,7 +1249,7 @@
 PHPAPI PHP_FUNCTION(ftell)
 {
 	zval *arg1;
-	long ret;
+	off_t ret;
 	php_stream *stream;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
@@ -1258,7 +1262,11 @@
 	if (ret == -1)	{
 		RETURN_FALSE;
 	}
-	RETURN_LONG(ret);
+        if (ret > LONG_MAX) {
+		RETURN_DOUBLE((double)ret);
+	} else {
+		RETURN_LONG(ret);
+	}
 }
 /* }}} */
 
@@ -1351,7 +1359,7 @@
 {
 	char *filename;
 	int filename_len;
-	int size = 0;
+	off_t size = 0;
 	zend_bool use_include_path = 0;
 	zval *zcontext = NULL;
 	php_stream *stream;
@@ -1367,7 +1375,11 @@
 	if (stream) {
 		size = php_stream_passthru(stream);
 		php_stream_close(stream);
-		RETURN_LONG(size);
+		if (size > LONG_MAX) {
+			RETURN_DOUBLE((double)size);
+		} else {
+			RETURN_LONG(size);
+		}
 	}
 
 	RETURN_FALSE;
@@ -1406,7 +1418,7 @@
 PHPAPI PHP_FUNCTION(fpassthru)
 {
 	zval *arg1;
-	int size;
+	off_t size;
 	php_stream *stream;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
@@ -1416,7 +1428,11 @@
 	PHP_STREAM_TO_ZVAL(stream, &arg1);
 
 	size = php_stream_passthru(stream);
-	RETURN_LONG(size);
+	if (size > LONG_MAX) {
+		RETURN_DOUBLE((double)size);
+	} else {
+		RETURN_LONG(size);
+	}
 }
 /* }}} */
 
@@ -1548,7 +1564,11 @@
 #else
 	MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
 #endif
-	MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
+        if (stat_ssb.sb.st_size > LONG_MAX) {
+		MAKE_DOUBLE_ZVAL_INCREF(stat_size, (double)stat_ssb.sb.st_size);
+        } else {
+		MAKE_LONG_ZVAL_INCREF(stat_size, (long)stat_ssb.sb.st_size);
+        }
 	MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime);
 	MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime);
 	MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_ssb.sb.st_ctime);
diff -ur php-5.5.1/ext/standard/filestat.c php-5.5.1.new/ext/standard/filestat.c
--- php-5.5.1/ext/standard/filestat.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/ext/standard/filestat.c	2013-08-15 10:42:39.442888060 +0200
@@ -966,7 +966,11 @@
 	case FS_INODE:
 		RETURN_LONG((long)ssb.sb.st_ino);
 	case FS_SIZE:
-		RETURN_LONG((long)ssb.sb.st_size);
+		if (ssb.sb.st_size > LONG_MAX) {
+			RETURN_DOUBLE((double)ssb.sb.st_size);
+		} else {
+			RETURN_LONG((long)ssb.sb.st_size);
+		}
 	case FS_OWNER:
 		RETURN_LONG((long)ssb.sb.st_uid);
 	case FS_GROUP:
@@ -1023,7 +1027,11 @@
 #else
 		MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
 #endif
-		MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
+		if (stat_sb->st_size > LONG_MAX) {
+			MAKE_DOUBLE_ZVAL_INCREF(stat_size, (double)stat_sb->st_size);
+		} else {
+			MAKE_LONG_ZVAL_INCREF(stat_size, (long)stat_sb->st_size);
+		}
 		MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
 		MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
 		MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
diff -ur php-5.5.1/ext/standard/php_filestat.h php-5.5.1.new/ext/standard/php_filestat.h
--- php-5.5.1/ext/standard/php_filestat.h	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/ext/standard/php_filestat.h	2013-08-15 10:42:39.442888060 +0200
@@ -66,6 +66,12 @@
 	ZVAL_LONG(name, val); \
 	Z_ADDREF_P(name); 
 
+#define MAKE_DOUBLE_ZVAL_INCREF(name, val)\
+       MAKE_STD_ZVAL(name); \
+       ZVAL_DOUBLE(name, val); \
+       Z_ADDREF_P(name); 
+
+
 #ifdef PHP_WIN32
 #define S_IRUSR S_IREAD
 #define S_IWUSR S_IWRITE
diff -ur php-5.5.1/ext/standard/streamsfuncs.c php-5.5.1.new/ext/standard/streamsfuncs.c
--- php-5.5.1/ext/standard/streamsfuncs.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/ext/standard/streamsfuncs.c	2013-08-15 10:42:39.442888060 +0200
@@ -452,8 +452,9 @@
 {
 	php_stream *src, *dest;
 	zval *zsrc, *zdest;
-	long maxlen = PHP_STREAM_COPY_ALL, pos = 0;
-	size_t len;
+	long maxlen = (long)PHP_STREAM_COPY_ALL, pos = 0;
+	off_t len;
+        off_t reallength = PHP_STREAM_COPY_ALL;
 	int ret;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|ll", &zsrc, &zdest, &maxlen, &pos) == FAILURE) {
@@ -468,12 +469,17 @@
 		RETURN_FALSE;
 	}
 
-	ret = php_stream_copy_to_stream_ex(src, dest, maxlen, &len);
+	reallength = maxlen == (long)PHP_STREAM_COPY_ALL ? PHP_STREAM_COPY_ALL : maxlen;
+	ret = php_stream_copy_to_stream_ex(src, dest, reallength, &len);
 
 	if (ret != SUCCESS) {
 		RETURN_FALSE;
 	}
-	RETURN_LONG(len);
+        if (len > LONG_MAX) {
+		RETURN_DOUBLE((double)len);
+	} else {
+		RETURN_LONG(len);
+	}
 }
 /* }}} */
 
diff -ur php-5.5.1/main/php_streams.h php-5.5.1.new/main/php_streams.h
--- php-5.5.1/main/php_streams.h	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/php_streams.h	2013-08-15 10:44:45.432887821 +0200
@@ -411,7 +411,7 @@
 #define php_stream_truncate_supported(stream)	(_php_stream_set_option((stream), PHP_STREAM_OPTION_TRUNCATE_API, PHP_STREAM_TRUNCATE_SUPPORTED, NULL TSRMLS_CC) == PHP_STREAM_OPTION_RETURN_OK ? 1 : 0)
 
 BEGIN_EXTERN_C()
-PHPAPI int _php_stream_truncate_set_size(php_stream *stream, size_t newsize TSRMLS_DC);
+PHPAPI int _php_stream_truncate_set_size(php_stream *stream, off_t newsize TSRMLS_DC);
 #define php_stream_truncate_set_size(stream, size)	_php_stream_truncate_set_size((stream), (size) TSRMLS_CC)
 END_EXTERN_C()
 
@@ -428,13 +428,13 @@
 
 /* copy up to maxlen bytes from src to dest.  If maxlen is PHP_STREAM_COPY_ALL,
  * copy until eof(src). */
-#define PHP_STREAM_COPY_ALL		((size_t)-1)
+#define PHP_STREAM_COPY_ALL		((off_t)-1)
 
 BEGIN_EXTERN_C()
 ZEND_ATTRIBUTE_DEPRECATED
 PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
 #define php_stream_copy_to_stream(src, dest, maxlen)	_php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
-PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC);
+PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, off_t maxlen, off_t *len STREAMS_DC TSRMLS_DC);
 #define php_stream_copy_to_stream_ex(src, dest, maxlen, len)	_php_stream_copy_to_stream_ex((src), (dest), (maxlen), (len) STREAMS_CC TSRMLS_CC)
 
 
@@ -445,7 +445,7 @@
 #define php_stream_copy_to_mem(src, buf, maxlen, persistent) _php_stream_copy_to_mem((src), (buf), (maxlen), (persistent) STREAMS_CC TSRMLS_CC)
 
 /* output all data from a stream */
-PHPAPI size_t _php_stream_passthru(php_stream * src STREAMS_DC TSRMLS_DC);
+PHPAPI off_t _php_stream_passthru(php_stream * src STREAMS_DC TSRMLS_DC);
 #define php_stream_passthru(stream)	_php_stream_passthru((stream) STREAMS_CC TSRMLS_CC)
 END_EXTERN_C()
 
diff -ur php-5.5.1/main/streams/memory.c php-5.5.1.new/main/streams/memory.c
--- php-5.5.1/main/streams/memory.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/memory.c	2013-08-29 21:22:26.892904548 +0200
@@ -255,7 +255,7 @@
 					if (ms->mode & TEMP_STREAM_READONLY) {
 						return PHP_STREAM_OPTION_RETURN_ERR;
 					}
-					newsize = *(size_t*)ptrparam;
+					newsize = *(off_t*)ptrparam;
 					if (newsize <= ms->fsize) {
 						if (newsize < ms->fpos) {
 							ms->fpos = newsize;
diff -ur php-5.5.1/main/streams/mmap.c php-5.5.1.new/main/streams/mmap.c
--- php-5.5.1/main/streams/mmap.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/mmap.c	2013-08-28 16:55:56.992883015 +0200
@@ -22,7 +22,7 @@
 #include "php.h"
 #include "php_streams_int.h"
 
-PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC)
+PHPAPI char *_php_stream_mmap_range(php_stream *stream, off_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC)
 {
 	php_stream_mmap_range range;
 	
diff -ur php-5.5.1/main/streams/php_stream_mmap.h php-5.5.1.new/main/streams/php_stream_mmap.h
--- php-5.5.1/main/streams/php_stream_mmap.h	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/php_stream_mmap.h	2013-08-28 16:55:03.722897870 +0200
@@ -48,7 +48,7 @@
 typedef struct {
 	/* requested offset and length.
 	 * If length is 0, the whole file is mapped */
-	size_t offset;
+	off_t offset;
 	size_t length;
 	
 	php_stream_mmap_access_t mode;
@@ -67,7 +67,7 @@
 #define php_stream_mmap_possible(stream)			(!php_stream_is_filtered((stream)) && php_stream_mmap_supported((stream)))
 
 BEGIN_EXTERN_C()
-PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC);
+PHPAPI char *_php_stream_mmap_range(php_stream *stream, off_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC);
 #define php_stream_mmap_range(stream, offset, length, mode, mapped_len)	_php_stream_mmap_range((stream), (offset), (length), (mode), (mapped_len) TSRMLS_CC)
 
 /* un-maps the last mapped range */
diff -ur php-5.5.1/main/streams/plain_wrapper.c php-5.5.1.new/main/streams/plain_wrapper.c
--- php-5.5.1/main/streams/plain_wrapper.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/plain_wrapper.c	2013-08-30 14:36:33.012883582 +0200
@@ -35,7 +35,14 @@
 #endif
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
+# ifndef PAGE_SIZE
+#  define PAGE_SIZE 4096
+# endif
 #endif
+#ifdef PHP_WIN32
+# define PAGE_SIZE 4096
+#endif
+
 #include "SAPI.h"
 
 #include "php_streams_int.h"
@@ -628,10 +635,12 @@
 			{
 				php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
 				int prot, flags;
+				off_t map_start = 0;
+                                size_t map_offset = 0;
 				
 				switch (value) {
 					case PHP_STREAM_MMAP_SUPPORTED:
-						return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
+						return fd == -1 || data->is_pipe ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
 
 					case PHP_STREAM_MMAP_MAP_RANGE:
 						do_fstat(data, 1);
@@ -665,7 +674,9 @@
 							default:
 								return PHP_STREAM_OPTION_RETURN_ERR;
 						}
-						range->mapped = (char*)mmap(NULL, range->length, prot, flags, fd, range->offset);
+                                                map_start = range->offset & ~(PAGE_SIZE - 1);
+                                                map_offset = (size_t)(range->offset - map_start);
+						range->mapped = (char*)mmap(NULL, range->length + map_offset, prot, flags, fd, map_start);
 						if (range->mapped == (char*)MAP_FAILED) {
 							range->mapped = NULL;
 							return PHP_STREAM_OPTION_RETURN_ERR;
@@ -673,6 +684,7 @@
 						/* remember the mapping */
 						data->last_mapped_addr = range->mapped;
 						data->last_mapped_len = range->length;
+                                                range->mapped = ((unsigned char*)range->mapped + map_offset); 
 						return PHP_STREAM_OPTION_RETURN_OK;
 
 					case PHP_STREAM_MMAP_UNMAP:
@@ -786,7 +798,8 @@
 					return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
 
 				case PHP_STREAM_TRUNCATE_SET_SIZE: {
-					ptrdiff_t new_size = *(ptrdiff_t*)ptrparam;
+					off_t new_size = *(off_t*)ptrparam;
+					/* Check for negative size, to keep backward compatibility with the previous behaviour */
 					if (new_size < 0) {
 						return PHP_STREAM_OPTION_RETURN_ERR;
 					}
diff -ur php-5.5.1/main/streams/streams.c php-5.5.1.new/main/streams/streams.c
--- php-5.5.1/main/streams/streams.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/streams.c	2013-08-30 14:54:44.622887454 +0200
@@ -1378,30 +1378,39 @@
 	return ret;
 }
 
-PHPAPI int _php_stream_truncate_set_size(php_stream *stream, size_t newsize TSRMLS_DC)
+PHPAPI int _php_stream_truncate_set_size(php_stream *stream, off_t newsize TSRMLS_DC)
 {
 	return php_stream_set_option(stream, PHP_STREAM_OPTION_TRUNCATE_API, PHP_STREAM_TRUNCATE_SET_SIZE, &newsize);
 }
 
-PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
+PHPAPI off_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
 {
-	size_t bcount = 0;
+	off_t bcount = 0;
 	char buf[8192];
 	int b;
 
 	if (php_stream_mmap_possible(stream)) {
-		char *p;
-		size_t mapped;
+		char *p = NULL;
+		size_t mapped = 0;
+                off_t final = 0;
+		off_t start = php_stream_tell(stream);
 
-		p = php_stream_mmap_range(stream, php_stream_tell(stream), PHP_STREAM_MMAP_ALL, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+		p = php_stream_mmap_range(stream, start, PHP_STREAM_MMAP_ALL, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
 
-		if (p) {
+		while (p && mapped)
+                {
 			PHPWRITE(p, mapped);
 
 			php_stream_mmap_unmap_ex(stream, mapped);
+                        final += mapped;
+		        p = php_stream_mmap_range(stream, start + final, PHP_STREAM_MMAP_ALL, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
 
-			return mapped;
 		}
+                if (p) {
+			php_stream_mmap_unmap_ex(stream, mapped);
+		}
+
+		return final;
 	}
 
 	while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
@@ -1426,7 +1435,7 @@
 		return 0;
 	}
 
-	if (maxlen == PHP_STREAM_COPY_ALL) {
+	if (maxlen == (size_t)PHP_STREAM_COPY_ALL) {
 		maxlen = 0;
 	}
 
@@ -1484,13 +1493,13 @@
 }
 
 /* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */
-PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)
+PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, off_t maxlen, off_t *len STREAMS_DC TSRMLS_DC)
 {
 	char buf[CHUNK_SIZE];
 	size_t readchunk;
-	size_t haveread = 0;
+	off_t haveread = 0;
 	size_t didread, didwrite, towrite;
-	size_t dummy;
+	off_t dummy;
 	php_stream_statbuf ssbuf;
 
 	if (!len) {
@@ -1521,24 +1530,34 @@
 		char *p;
 		size_t mapped;
 
-		p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+                off_t final = 0, start = php_stream_tell(src), mapsum = 0;
+                size_t mappedlen = maxlen < SIZE_MAX ? (size_t)maxlen : (size_t)-1;
 
-		if (p) {
+                p = php_stream_mmap_range(src, start, maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+
+		while (p && mapped > 0) {
+			mapsum += (off_t)mapped;
 			didwrite = php_stream_write(dest, p, mapped);
 
+                        final += didwrite;
+                        if ((maxlen && final >= maxlen) || mapped < mappedlen) break;
+			/* Ok, map another section to fit the address space for a larger file */
+			php_stream_mmap_unmap_ex(src, mapped);
+                        mappedlen = (maxlen - final ) < SIZE_MAX ? (size_t)(maxlen - final) : (size_t)-1;
+                        p = php_stream_mmap_range(src, start + final, mappedlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+                }
+                *len = final;
+		if (p) {
 			php_stream_mmap_unmap_ex(src, mapped);
-
-			*len = didwrite;
-
-			/* we've got at least 1 byte to read
-			 * less than 1 is an error
-			 * AND read bytes match written */
-			if (mapped > 0 && mapped == didwrite) {
-				return SUCCESS;
-			}
-			return FAILURE;
 		}
-	}
+
+                /* we've got at least 1 byte to read.
+                * less than 1 is an error */
+                if (final > 0 && mapsum == final) {
+                       return SUCCESS;
+                }
+                return FAILURE;
+        }
 
 	while(1) {
 		readchunk = sizeof(buf);
@@ -1593,12 +1612,12 @@
 ZEND_ATTRIBUTE_DEPRECATED
 PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC)
 {
-	size_t len;
-	int ret = _php_stream_copy_to_stream_ex(src, dest, maxlen, &len STREAMS_REL_CC TSRMLS_CC);
-	if (ret == SUCCESS && len == 0 && maxlen != 0) {
+        off_t _len = 0, _maxlen = maxlen;
+	int ret = _php_stream_copy_to_stream_ex(src, dest, _maxlen, &_len STREAMS_REL_CC TSRMLS_CC);
+	if (ret == SUCCESS && _len == 0 && _maxlen != 0) {
 		return 1;
 	}
-	return len;
+	return (size_t)_len;
 }
 /* }}} */
 
diff -ur php-5.5.1/main/streams/userspace.c php-5.5.1.new/main/streams/userspace.c
--- php-5.5.1/main/streams/userspace.c	2013-07-18 16:37:33.000000000 +0200
+++ php-5.5.1.new/main/streams/userspace.c	2013-08-30 14:40:13.352891754 +0200
@@ -1036,8 +1036,8 @@
 			break;
 
 		case PHP_STREAM_TRUNCATE_SET_SIZE: {
-			ptrdiff_t new_size = *(ptrdiff_t*) ptrparam;
-			if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) {
+			off_t new_size = *(off_t*) ptrparam;
+			if (new_size >= 0 && new_size <= (off_t)LONG_MAX) {
 				MAKE_STD_ZVAL(zvalue);
 				ZVAL_LONG(zvalue, (long)new_size);
 				args[0] = &zvalue;
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 00:01:30 2024 UTC