ID: 48886 Comment by: mail dot pourri at laposte dot net Reported By: mail dot pourri at laposte dot net Status: Open Bug Type: Feature/Change Request Operating System: All PHP Version: 5.3.0 New Comment:
diff -aur php-5.3.0.orig/ext/phar/phar_internal.h php-5.3.0/ext/phar/phar_internal.h --- php-5.3.0.orig/ext/phar/phar_internal.h 2009-05-13 22:25:43.000000000 +0200 +++ php-5.3.0/ext/phar/phar_internal.h 2009-07-11 15:10:04.000000000 +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 -aur php-5.3.0.orig/ext/standard/file.c php-5.3.0/ext/standard/file.c --- php-5.3.0.orig/ext/standard/file.c 2009-06-22 13:37:30.000000000 +0200 +++ php-5.3.0/ext/standard/file.c 2009-07-11 15:23:32.000000000 +0200 @@ -594,7 +594,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; @@ -642,7 +642,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 { @@ -659,9 +659,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; } } @@ -680,13 +680,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; @@ -702,9 +702,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); @@ -721,7 +721,11 @@ RETURN_FALSE; } - RETURN_LONG(numbytes); + if (numbytes > LONG_MAX) { + RETURN_DOUBLE((double)numbytes); + } else { + RETURN_LONG(numbytes); + } } /* }}} */ @@ -1322,7 +1326,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) { @@ -1335,7 +1339,11 @@ if (ret == -1) { RETURN_FALSE; } - RETURN_LONG(ret); + if (ret > LONG_MAX) { + RETURN_DOUBLE((double)ret); + } else { + RETURN_LONG(ret); + } } /* }}} */ @@ -1432,7 +1440,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; @@ -1448,7 +1456,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; @@ -1487,7 +1499,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) { @@ -1497,7 +1509,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); + } } /* }}} */ @@ -1629,7 +1645,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); + } #ifdef NETWARE MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime.tv_sec); MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime.tv_sec); diff -aur php-5.3.0.orig/ext/standard/filestat.c php-5.3.0/ext/standard/filestat.c --- php-5.3.0.orig/ext/standard/filestat.c 2008-12-31 12:15:45.000000000 +0100 +++ php-5.3.0/ext/standard/filestat.c 2009-07-05 12:20:58.000000000 +0200 @@ -893,7 +893,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: @@ -962,7 +966,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); + } #ifdef NETWARE MAKE_LONG_ZVAL_INCREF(stat_atime, (stat_sb->st_atime).tv_sec); MAKE_LONG_ZVAL_INCREF(stat_mtime, (stat_sb->st_mtime).tv_sec); diff -aur php-5.3.0.orig/ext/standard/php_filestat.h php-5.3.0/ext/standard/php_filestat.h --- php-5.3.0.orig/ext/standard/php_filestat.h 2008-12-31 12:15:45.000000000 +0100 +++ php-5.3.0/ext/standard/php_filestat.h 2009-07-05 11:45:48.000000000 +0200 @@ -64,6 +64,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 -aur php-5.3.0.orig/ext/standard/streamsfuncs.c php-5.3.0/ext/standard/streamsfuncs.c --- php-5.3.0.orig/ext/standard/streamsfuncs.c 2009-04-19 19:10:35.000000000 +0200 +++ php-5.3.0/ext/standard/streamsfuncs.c 2009-07-11 15:23:31.000000000 +0200 @@ -442,8 +442,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) { @@ -458,12 +459,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 -aur php-5.3.0.orig/main/php_streams.h php-5.3.0/main/php_streams.h --- php-5.3.0.orig/main/php_streams.h 2009-04-19 19:10:34.000000000 +0200 +++ php-5.3.0/main/php_streams.h 2009-07-05 12:36:06.000000000 +0200 @@ -401,7 +401,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() @@ -418,13 +418,13 @@ /* copy up to maxlen bytes from src to dest. If maxlen is PHP_STREAM_COPY_ALL, copy until eof(src). * Uses mmap if the src is a plain file and at offset 0 */ -#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 size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC); +PHPAPI size_t _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) @@ -435,7 +435,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 -aur php-5.3.0.orig/main/streams/php_stream_mmap.h php-5.3.0/main/streams/php_stream_mmap.h --- php-5.3.0.orig/main/streams/php_stream_mmap.h 2009-05-17 16:58:10.000000000 +0200 +++ php-5.3.0/main/streams/php_stream_mmap.h 2009-07-07 20:30:59.000000000 +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; diff -aur php-5.3.0.orig/main/streams/plain_wrapper.c php-5.3.0/main/streams/plain_wrapper.c --- php-5.3.0.orig/main/streams/plain_wrapper.c 2009-04-11 13:44:15.000000000 +0200 +++ php-5.3.0/main/streams/plain_wrapper.c 2009-07-11 15:00:01.000000000 +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" @@ -624,6 +631,8 @@ { 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: @@ -661,7 +670,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; @@ -669,6 +680,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: diff -aur php-5.3.0.orig/main/streams/streams.c php-5.3.0/main/streams/streams.c --- php-5.3.0.orig/main/streams/streams.c 2009-05-17 16:58:10.000000000 +0200 +++ php-5.3.0/main/streams/streams.c 2009-07-11 15:11:22.000000000 +0200 @@ -918,7 +918,7 @@ buf = emalloc(toread + 1); *returned_len = php_stream_read(stream, buf, toread); - if (*returned_len >= 0) { + if ((ssize_t)*returned_len >= 0) { if (skip) { stream->readpos += delim_len; stream->position += delim_len; @@ -1200,30 +1200,35 @@ 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; + 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) + { 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; } + return final; } while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) { @@ -1248,7 +1253,7 @@ return 0; } - if (maxlen == PHP_STREAM_COPY_ALL) { + if (maxlen == (size_t)PHP_STREAM_COPY_ALL) { maxlen = 0; } @@ -1298,13 +1303,13 @@ } /* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */ -PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC) +PHPAPI size_t _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; - size_t dummy; + off_t dummy = 0; php_stream_statbuf ssbuf; if (!len) { @@ -1334,24 +1339,29 @@ if (php_stream_mmap_possible(src)) { char *p; size_t mapped; + off_t final = 0, start = php_stream_tell(src); + size_t mappedlen = maxlen < LONG_MAX ? (size_t)maxlen : (size_t)-1; - p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); + p = php_stream_mmap_range(src, start, mappedlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); - if (p) { + while (p && mapped > 0) { mapped = php_stream_write(dest, p, mapped); php_stream_mmap_unmap_ex(src, mapped); + final += mapped; + if ((maxlen && final >= maxlen) || mapped < mappedlen) break; + mappedlen = (maxlen - final ) < LONG_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 = mapped; - - /* we've got at least 1 byte to read. - * less than 1 is an error */ - - if (mapped > 0) { - return SUCCESS; - } - return FAILURE; + *len = final; + + /* we've got at least 1 byte to read. + * less than 1 is an error */ + if (mapped > 0) { + return SUCCESS; } + return FAILURE; } while(1) { @@ -1408,12 +1418,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; } /* }}} */ Previous Comments: ------------------------------------------------------------------------ [2009-07-11 13:37:58] mail dot pourri at laposte dot net Description: ------------ As currently all integers are 32 bits on 32 bits processor, even when php is compiled with Large File Support, all the functions that use integer instead of a right format (stat, filesize, ftell, etc...) don't report the right size when a file is > 4GB. The attached patch solve the issue by using doubles instead of int when a size overflow 32 bits (so as IEEE754 specifies, we have 53 bits of real, integer, value in a double). Unlike Wes patch posted earlier, that didn't work, I've modified all the code that still used size_t to use off_t, modifying the extensions too, memory mapping (that had a bug as it previously failed when offset used, BTW), etc... It works when applyied to released 5.3.0 with patch -p1. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=48886&edit=1