mirror of
https://github.com/php/php-src.git
synced 2024-09-23 19:07:26 +00:00
MFB5.3: Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams)
This commit is contained in:
parent
bba5d66bf8
commit
069c0fdc80
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user