From: Arnaud Le Blanc Date: Sun, 19 Apr 2009 13:50:25 +0000 (+0000) Subject: MFB5.3: Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams) X-Git-Tag: php-5.4.0alpha1~191^2~3907 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=069c0fdc802f6aec55284802f191d13627c65f30;p=php MFB5.3: Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams) --- diff --git a/ext/standard/file.c b/ext/standard/file.c index 495660ab71..5f864ec963 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -662,7 +662,10 @@ PHP_FUNCTION(file_put_contents) switch (Z_TYPE_P(data)) { case IS_RESOURCE: - numchars = php_stream_copy_to_stream(srcstream, stream, PHP_STREAM_COPY_ALL); + numchars = (int) php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL); + if ((size_t)numchars == PHP_STREAM_FAILURE) { + numchars = -1; + } break; case IS_ARRAY: if (zend_hash_num_elements(Z_ARRVAL_P(data))) { @@ -1949,7 +1952,7 @@ safe_to_copy: deststream = php_stream_open_wrapper(dest, "wb", REPORT_ERRORS, NULL); if (srcstream && deststream) { - ret = php_stream_copy_to_stream(srcstream, deststream, PHP_STREAM_COPY_ALL) == 0 ? FAILURE : SUCCESS; + ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL) == PHP_STREAM_FAILURE ? FAILURE : SUCCESS; } if (srcstream) { php_stream_close(srcstream); diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index eb03b09b5c..ce2cfcc6ef 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -458,6 +458,7 @@ PHP_FUNCTION(stream_copy_to_stream) php_stream *src, *dest; zval *zsrc, *zdest; long maxlen = PHP_STREAM_COPY_ALL, pos = 0; + size_t ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|ll", &zsrc, &zdest, &maxlen, &pos) == FAILURE) { RETURN_FALSE; @@ -471,7 +472,12 @@ PHP_FUNCTION(stream_copy_to_stream) RETURN_FALSE; } - RETURN_LONG(php_stream_copy_to_stream(src, dest, maxlen)); + ret = php_stream_copy_to_stream_ex(src, dest, maxlen); + + if (ret == PHP_STREAM_FAILURE) { + RETURN_FALSE; + } + RETURN_LONG(ret); } /* }}} */ diff --git a/main/php_streams.h b/main/php_streams.h index 7e57b20cff..2bf01ae788 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -525,14 +525,25 @@ END_EXTERN_C() * Uses mmap if the src is a plain file and at offset 0 */ #define PHP_STREAM_COPY_ALL ((size_t)-1) +#define PHP_STREAM_FAILURE ((size_t)-1) + BEGIN_EXTERN_C() +ZEND_ATTRIBUTE_DEPRECATED PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, size_t maxchars STREAMS_DC TSRMLS_DC); +ZEND_ATTRIBUTE_DEPRECATED PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC); /* Preserve "characters" semantics by having maxlen refer to maxchars in a unicode context */ #define php_stream_copy_to_stream(src, dest, maxlen) ( ((src)->readbuf_type == IS_STRING) \ ? _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC) \ : _php_stream_ucopy_to_stream((src), (dest), -1, (maxlen) STREAMS_CC TSRMLS_CC) ) +PHPAPI size_t _php_stream_ucopy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t maxchars STREAMS_DC TSRMLS_DC); +PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC); +/* Preserve "characters" semantics by having maxlen refer to maxchars in a unicode context */ +#define php_stream_copy_to_stream_ex(src, dest, maxlen) ( ((src)->readbuf_type == IS_STRING) \ + ? _php_stream_copy_to_stream_ex((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC) \ + : _php_stream_ucopy_to_stream_ex((src), (dest), -1, (maxlen) STREAMS_CC TSRMLS_CC) ) + /* read all data from stream and put into a buffer. Caller must free buffer when done. * The copy will use mmap if available. */ PHPAPI size_t _php_stream_copy_to_mem_ex(php_stream *src, zend_uchar rettype, void **buf, size_t maxlen, size_t maxchars, diff --git a/main/streams/cast.c b/main/streams/cast.c index 69ec4b8a0e..8a021209f3 100644 --- a/main/streams/cast.c +++ b/main/streams/cast.c @@ -214,9 +214,9 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show newstream = php_stream_fopen_tmpfile(); if (newstream) { - size_t copied = php_stream_copy_to_stream(stream, newstream, PHP_STREAM_COPY_ALL); + size_t copied = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL); - if (copied == 0) { + if (copied == PHP_STREAM_FAILURE) { php_stream_close(newstream); } else { int retcode = php_stream_cast(newstream, castas | flags, ret, show_err); @@ -332,7 +332,7 @@ PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstr (*newstream)->open_lineno = origstream->open_lineno; #endif - if (php_stream_copy_to_stream(origstream, *newstream, PHP_STREAM_COPY_ALL) == 0) { + if (php_stream_copy_to_stream_ex(origstream, *newstream, PHP_STREAM_COPY_ALL) == PHP_STREAM_FAILURE) { php_stream_close(*newstream); *newstream = NULL; return PHP_STREAM_CRITICAL; diff --git a/main/streams/streams.c b/main/streams/streams.c index 490242429d..746b325daa 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1768,14 +1768,14 @@ PHPAPI size_t _php_stream_copy_to_mem_ex(php_stream *src, zend_uchar rettype, vo } /* Designed for copying UChars (taking into account both maxlen and maxchars) */ -PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, size_t maxchars STREAMS_DC TSRMLS_DC) +PHPAPI size_t _php_stream_ucopy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t maxchars STREAMS_DC TSRMLS_DC) { size_t haveread = 0; php_stream_statbuf ssbuf; if (src->readbuf_type == IS_STRING) { /* Called incorrectly, don't do that. */ - return _php_stream_copy_to_stream(src, dest, maxlen STREAMS_CC TSRMLS_CC); + return _php_stream_copy_to_stream_ex(src, dest, maxlen STREAMS_CC TSRMLS_CC); } if (maxlen == 0 || maxchars == 0) { @@ -1787,8 +1787,6 @@ PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, siz } if (php_stream_stat(src, &ssbuf) == 0) { - /* in the event that the source file is 0 bytes, return 1 to indicate success - * because opening the file to write had already created a copy */ if (ssbuf.sb.st_size == 0 #ifdef S_ISFIFO && !S_ISFIFO(ssbuf.sb.st_mode) @@ -1797,7 +1795,7 @@ PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, siz && !S_ISCHR(ssbuf.sb.st_mode) #endif ) { - return 1; + return 0; } } @@ -1829,14 +1827,14 @@ PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, siz while(towrite) { didwrite = php_stream_write_unicode(dest, writeptr, towrite); if (didwrite == 0) { - return 0; /* error */ + return PHP_STREAM_FAILURE; } towrite -= didwrite; writeptr += didwrite; } } else { - return haveread; + break; } if (maxchars == 0 || maxlen - haveread == 0) { @@ -1844,18 +1842,36 @@ PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, siz } } - return haveread; + /* we've got at least 1 byte to read. + * less than 1 is an error */ + + if (haveread > 0) { + return haveread; + } + return PHP_STREAM_FAILURE; +} + +/* see _php_stream_copy_to_stream() */ +ZEND_ATTRIBUTE_DEPRECATED +PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, size_t maxchars STREAMS_DC TSRMLS_DC) +{ + size_t ret = _php_stream_ucopy_to_stream_ex(src, dest, maxlen, maxchars STREAMS_REL_CC TSRMLS_CC); + if (ret == 0 && maxlen != 0 && maxchars != 0) { + return 1; + } + return ret; } /* Optimized for copying octets from source stream */ -PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC) +/* Returns the number of bytes moved, or PHP_STREAM_FAILURE on failure. */ +PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC) { size_t haveread = 0; php_stream_statbuf ssbuf; if (src->readbuf_type == IS_UNICODE) { /* Called incorrectly, don't do that. */ - return _php_stream_ucopy_to_stream(src, dest, maxlen, -1 STREAMS_CC TSRMLS_CC); + return _php_stream_ucopy_to_stream_ex(src, dest, maxlen, -1 STREAMS_CC TSRMLS_CC); } if (maxlen == 0) { @@ -1867,8 +1883,6 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size } if (php_stream_stat(src, &ssbuf) == 0) { - /* in the event that the source file is 0 bytes, return 1 to indicate success - * because opening the file to write had already created a copy */ if (ssbuf.sb.st_size == 0 #ifdef S_ISFIFO && !S_ISFIFO(ssbuf.sb.st_mode) @@ -1877,7 +1891,7 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size && !S_ISCHR(ssbuf.sb.st_mode) #endif ) { - return 1; + return 0; } } @@ -1891,8 +1905,14 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size mapped = php_stream_write(dest, p, mapped); php_stream_mmap_unmap(src); + + /* we've got at least 1 byte to read. + * less than 1 is an error */ - return mapped; + if (mapped > 0) { + return mapped; + } + return PHP_STREAM_FAILURE; } } @@ -1919,14 +1939,14 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size while(towrite) { didwrite = php_stream_write(dest, writeptr, towrite); if (didwrite == 0) { - return 0; /* error */ + return PHP_STREAM_FAILURE; } towrite -= didwrite; writeptr += didwrite; } } else { - return haveread; + break; } if (maxlen - haveread == 0) { @@ -1934,7 +1954,26 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size } } - return haveread; + /* we've got at least 1 byte to read. + * less than 1 is an error */ + + if (haveread > 0) { + return haveread; + } + return PHP_STREAM_FAILURE; +} + +/* Returns the number of bytes moved. + * Returns 1 when source len is 0. + * Deprecated in favor of php_stream_copy_to_stream_ex() */ +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 ret = _php_stream_copy_to_stream_ex(src, dest, maxlen STREAMS_REL_CC TSRMLS_CC); + if (ret == 0 && maxlen != 0) { + return 1; + } + return ret; } /* }}} */