summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--ext/standard/php_fopen_wrapper.c13
-rw-r--r--ext/standard/tests/streams/bug75031.phpt25
-rw-r--r--main/php_memory_streams.h12
-rw-r--r--main/streams/memory.c30
5 files changed, 65 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index 035eac82b8..842b9a3924 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ PHP NEWS
. Redesigned the old ext_skel program written in PHP, run:
'php ext_skel.php' for all options. This means there is no dependencies
thrus making it work on Windows out of the box. (Kalle)
+ . Fixed bug #75031 (support append mode in temp/memory streams). (adsr)
- cURL:
. Fixed bug #74125 (Fixed finding CURL on systems with multiarch support).
diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c
index 0031440704..34f5d3afbf 100644
--- a/ext/standard/php_fopen_wrapper.c
+++ b/ext/standard/php_fopen_wrapper.c
@@ -28,6 +28,7 @@
#include "php.h"
#include "php_globals.h"
#include "php_standard.h"
+#include "php_memory_streams.h"
#include "php_fopen_wrappers.h"
#include "SAPI.h"
@@ -203,20 +204,12 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa
return NULL;
}
}
- if (strpbrk(mode, "wa+")) {
- mode_rw = TEMP_STREAM_DEFAULT;
- } else {
- mode_rw = TEMP_STREAM_READONLY;
- }
+ mode_rw = php_stream_mode_from_str(mode);
return php_stream_temp_create(mode_rw, max_memory);
}
if (!strcasecmp(path, "memory")) {
- if (strpbrk(mode, "wa+")) {
- mode_rw = TEMP_STREAM_DEFAULT;
- } else {
- mode_rw = TEMP_STREAM_READONLY;
- }
+ mode_rw = php_stream_mode_from_str(mode);
return php_stream_memory_create(mode_rw);
}
diff --git a/ext/standard/tests/streams/bug75031.phpt b/ext/standard/tests/streams/bug75031.phpt
new file mode 100644
index 0000000000..f0d67a3524
--- /dev/null
+++ b/ext/standard/tests/streams/bug75031.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #75031: Append mode in php://temp and php://memory
+--FILE--
+<?php
+
+function test_75031($type, $mode) {
+ $fp = fopen($type, $mode);
+ fwrite($fp, "hello");
+ fseek($fp, 0, SEEK_SET);
+ fwrite($fp, "world");
+ var_dump(stream_get_contents($fp, -1, 0));
+ fclose($fp);
+}
+
+test_75031("php://temp", "w+");
+test_75031("php://memory", "w+");
+test_75031("php://temp", "a+");
+test_75031("php://memory", "a+");
+
+?>
+--EXPECT--
+string(5) "world"
+string(5) "world"
+string(10) "helloworld"
+string(10) "helloworld"
diff --git a/main/php_memory_streams.h b/main/php_memory_streams.h
index f8989d261b..271a9276e0 100644
--- a/main/php_memory_streams.h
+++ b/main/php_memory_streams.h
@@ -25,9 +25,10 @@
#define PHP_STREAM_MAX_MEM 2 * 1024 * 1024
-#define TEMP_STREAM_DEFAULT 0
-#define TEMP_STREAM_READONLY 1
-#define TEMP_STREAM_TAKE_BUFFER 2
+#define TEMP_STREAM_DEFAULT 0x0
+#define TEMP_STREAM_READONLY 0x1
+#define TEMP_STREAM_TAKE_BUFFER 0x2
+#define TEMP_STREAM_APPEND 0x4
#define php_stream_memory_create(mode) _php_stream_memory_create((mode) STREAMS_CC)
#define php_stream_memory_create_rel(mode) _php_stream_memory_create((mode) STREAMS_REL_CC)
@@ -41,6 +42,7 @@
#define php_stream_temp_open(mode, max_memory_usage, buf, length) _php_stream_temp_open((mode), (max_memory_usage), (buf), (length) STREAMS_CC)
BEGIN_EXTERN_C()
+
PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC);
PHPAPI php_stream *_php_stream_memory_open(int mode, char *buf, size_t length STREAMS_DC);
PHPAPI char *_php_stream_memory_get_buffer(php_stream *stream, size_t *length STREAMS_DC);
@@ -48,6 +50,10 @@ PHPAPI char *_php_stream_memory_get_buffer(php_stream *stream, size_t *length ST
PHPAPI php_stream *_php_stream_temp_create(int mode, size_t max_memory_usage STREAMS_DC);
PHPAPI php_stream *_php_stream_temp_create_ex(int mode, size_t max_memory_usage, const char *tmpdir STREAMS_DC);
PHPAPI php_stream *_php_stream_temp_open(int mode, size_t max_memory_usage, char *buf, size_t length STREAMS_DC);
+
+PHPAPI int php_stream_mode_from_str(const char *mode);
+PHPAPI const char *_php_stream_mode_to_str(int mode);
+
END_EXTERN_C()
extern PHPAPI php_stream_ops php_stream_memory_ops;
diff --git a/main/streams/memory.c b/main/streams/memory.c
index 7af87c7efb..2809e22ed0 100644
--- a/main/streams/memory.c
+++ b/main/streams/memory.c
@@ -53,10 +53,11 @@ static size_t php_stream_memory_write(php_stream *stream, const char *buf, size_
if (ms->mode & TEMP_STREAM_READONLY) {
return 0;
+ } else if (ms->mode & TEMP_STREAM_APPEND) {
+ ms->fpos = ms->fsize;
}
if (ms->fpos + count > ms->fsize) {
char *tmp;
-
if (!ms->data) {
tmp = emalloc(ms->fpos + count);
} else {
@@ -276,6 +277,29 @@ PHPAPI php_stream_ops php_stream_memory_ops = {
php_stream_memory_set_option
};
+/* {{{ */
+PHPAPI int php_stream_mode_from_str(const char *mode)
+{
+ if (strpbrk(mode, "a")) {
+ return TEMP_STREAM_APPEND;
+ } else if (strpbrk(mode, "w+")) {
+ return TEMP_STREAM_DEFAULT;
+ }
+ return TEMP_STREAM_READONLY;
+}
+/* }}} */
+
+/* {{{ */
+PHPAPI const char *_php_stream_mode_to_str(int mode)
+{
+ if (mode == TEMP_STREAM_READONLY) {
+ return "rb";
+ } else if (mode == TEMP_STREAM_APPEND) {
+ return "a+b";
+ }
+ return "w+b";
+}
+/* }}} */
/* {{{ */
PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC)
@@ -290,7 +314,7 @@ PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC)
self->smax = ~0u;
self->mode = mode;
- stream = php_stream_alloc_rel(&php_stream_memory_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
+ stream = php_stream_alloc_rel(&php_stream_memory_ops, self, 0, _php_stream_mode_to_str(mode));
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
return stream;
}
@@ -564,7 +588,7 @@ PHPAPI php_stream *_php_stream_temp_create_ex(int mode, size_t max_memory_usage,
if (tmpdir) {
self->tmpdir = estrdup(tmpdir);
}
- stream = php_stream_alloc_rel(&php_stream_temp_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
+ stream = php_stream_alloc_rel(&php_stream_temp_ops, self, 0, _php_stream_mode_to_str(mode));
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
self->innerstream = php_stream_memory_create_rel(mode);
php_stream_encloses(stream, self->innerstream);