]> granicus.if.org Git - php/commitdiff
Miscellaneous streams fixes, including probable fixes for:
authorWez Furlong <wez@php.net>
Sat, 22 Feb 2003 02:43:58 +0000 (02:43 +0000)
committerWez Furlong <wez@php.net>
Sat, 22 Feb 2003 02:43:58 +0000 (02:43 +0000)
Bug #21131 (fopen with 'a+' and rewind() doesn't work)
Bug #21713 (include remote files leaks temporary files + descriptors on Solaris)
Bug #21185 (move_uploaded_file() does not ignore open_basedir as it should)
Bug #22362 (combinations of fwrite(), fread() and fseek() produce unexpected results)

ext/standard/file.c
ext/standard/tests/file/bug21131.phpt
ext/standard/tests/file/bug22362.phpt [new file with mode: 0644]
main/php_streams.h
main/streams.c

index fbb5a3297a28001a928a0e09bced1ea73ecdb0b4..e565f9f00cdefd657486be405faab50e5ccc7b9a 100644 (file)
@@ -2038,7 +2038,7 @@ PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC)
        int ret = FAILURE;
 
        srcstream = php_stream_open_wrapper(src, "rb", 
-                               ENFORCE_SAFE_MODE | REPORT_ERRORS,
+                               STREAM_DISABLE_OPEN_BASEDIR | REPORT_ERRORS,
                                NULL);
        
        if (!srcstream) 
index 00c3781f9c450fb896c3f51515ccf29c52068c50..7950f9fd0de4c585e13f7ef5700e4e1ce3ac171e 100644 (file)
@@ -9,15 +9,10 @@ fwrite($fp, "foobar");
 fclose($fp);
 
 $fp = fopen($filename, "a+");
-var_dump(ftell($fp));
 rewind($fp);
-var_dump(ftell($fp));
 fpassthru($fp);
 fclose($fp);
 unlink($filename);
 ?>
 --EXPECT--
-int(6)
-int(0)
 foobar
-
diff --git a/ext/standard/tests/file/bug22362.phpt b/ext/standard/tests/file/bug22362.phpt
new file mode 100644 (file)
index 0000000..ce88bf3
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #22362: combinations of fseek() and fwrite() produce unexpected results.
+--FILE--
+<?php # vim600:syn=php:
+$filename = tempnam("/tmp", "phpt");
+
+$fp = fopen($filename, "w+") or die("can't open $filename for append");
+fwrite($fp, "quxbar");
+fseek($fp, 3, SEEK_SET);
+fread($fp, 1);
+fseek($fp, 4, SEEK_SET);
+fwrite($fp, '!');
+fseek($fp, 0, SEEK_SET);
+var_dump(fread($fp, 4095));
+
+ftruncate($fp, 0);
+rewind($fp);
+
+fwrite($fp, "barfoo");
+fseek($fp, 3, SEEK_SET);
+fread($fp, 1);
+fwrite($fp, '!');
+fseek($fp, 0, SEEK_SET);
+var_dump(fread($fp, 4095));
+
+fclose($fp);
+unlink($filename);
+?>
+--EXPECT--
+string(6) "quxb!r"
+string(6) "barf!o"
index c506b060f2ccae6c5edde85786b511b1088af503..4033df6c51ae47e8976f3828a0774454b2e56926 100755 (executable)
@@ -502,6 +502,11 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
 /* this flag is only used by include/require functions */
 #define STREAM_OPEN_FOR_INCLUDE                128
 
+/* 512 skipped for PHP 5 compat */
+
+/* if set, skip open_basedir checks */
+#define STREAM_DISABLE_OPEN_BASEDIR    1024
+
 /* Antique - no longer has meaning */
 #define IGNORE_URL_WIN 0
 
index 4f8454989d916b1f8a71864a39fe8101b2dc07df..4558ed86639628def27e35a0d4a8d775dcbd1197 100755 (executable)
@@ -852,6 +852,15 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun
        if (buf == NULL || count == 0 || stream->ops->write == NULL)
                return 0;
 
+       /* if we have a seekable stream we need to ensure that data is written at the
+        * current stream->position. This means invalidating the read buffer and then
+        * performing a low-level seek */
+       if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
+               stream->readpos = stream->writepos = 0;
+
+               stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position TSRMLS_CC);
+       }
+       
        while (count > 0) {
                towrite = count;
                if (towrite > stream->chunk_size)
@@ -871,8 +880,6 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun
                         * buffered from fifos and sockets */
                        if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
                                stream->position += justwrote;
-                               stream->writepos = 0;
-                               stream->readpos = 0;
                        }
                } else {
                        break;
@@ -907,10 +914,6 @@ PHPAPI off_t _php_stream_tell(php_stream *stream TSRMLS_DC)
 
 PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_DC)
 {
-       /* not moving anywhere */
-       if ((offset == 0 && whence == SEEK_CUR) || (offset == stream->position && whence == SEEK_SET))
-               return 0;
-
        /* handle the case where we are in the buffer */
        if ((stream->flags & PHP_STREAM_FLAG_NO_BUFFER) == 0) {
                switch(whence) {
@@ -933,9 +936,6 @@ PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_
                                break;
                }
        }
-       
-       /* invalidate the buffer contents */
-       stream->readpos = stream->writepos = 0;
 
        if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
                int ret;
@@ -954,6 +954,10 @@ PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_
                if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0) {
                        if (ret == 0)
                                stream->eof = 0;
+
+                       /* invalidate the buffer contents */
+                       stream->readpos = stream->writepos = 0;
+
                        return ret;
                }
                /* else the stream has decided that it can't support seeking after all;
@@ -1996,7 +2000,12 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
                return FAILURE;
 #endif
 
-               if (flags & PHP_STREAM_CAST_TRY_HARD) {
+               if (!stream->filterhead && stream->ops->cast && stream->ops->cast(stream, castas, NULL TSRMLS_CC) == SUCCESS) {
+                       if (FAILURE == stream->ops->cast(stream, castas, ret TSRMLS_CC)) {
+                               return FAILURE;
+                       }
+                       goto exit_success;
+               } else if (flags & PHP_STREAM_CAST_TRY_HARD) {
                        php_stream *newstream;
 
                        newstream = php_stream_fopen_tmpfile();
@@ -2195,7 +2204,7 @@ static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, ch
                return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path, options);
        }
 
-       if (php_check_open_basedir(path TSRMLS_CC)) {
+       if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(path TSRMLS_CC)) {
                return NULL;
        }