]> granicus.if.org Git - php/commitdiff
MFB5.3: Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams)
authorArnaud Le Blanc <lbarnaud@php.net>
Sun, 19 Apr 2009 13:50:25 +0000 (13:50 +0000)
committerArnaud Le Blanc <lbarnaud@php.net>
Sun, 19 Apr 2009 13:50:25 +0000 (13:50 +0000)
ext/standard/file.c
ext/standard/streamsfuncs.c
main/php_streams.h
main/streams/cast.c
main/streams/streams.c

index 495660ab71a8573c680e4787120c07f5585d0fe5..5f864ec963e1b592f1c3e340710abdf68dfcbfae 100644 (file)
@@ -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);
index eb03b09b5cd23fd30462451f53af79aa00828dd5..ce2cfcc6efa71c709ad508141b9167f0a5827f05 100644 (file)
@@ -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);
 }
 /* }}} */
 
index 7e57b20cff74b7d28b6b3ef9201df5c065a97eea..2bf01ae7881cc6ace173553d95bc2e58522ca018 100755 (executable)
@@ -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,
index 69ec4b8a0e2e15cf0c8a5a9415eb9a018166ade3..8a021209f367039c6c9409a87adee465f8b02306 100644 (file)
@@ -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;
index 490242429d849fb38a286b2eb0414bf4498e5c52..746b325daad4f2cd45b6241704e905c424461587 100755 (executable)
@@ -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;
 }
 /* }}} */