summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2012-08-07 22:59:12 -0700
committerStanislav Malyshev <stas@php.net>2012-08-07 22:59:12 -0700
commit4db70fd406c805a296f4531088fe716a1ef67158 (patch)
tree918530e294cdaec54601c9bd401e52eb7a25f2fe
parent01e414bb6fb1f1939df3b45d3cd64f140f91e440 (diff)
downloadphp-git-4db70fd406c805a296f4531088fe716a1ef67158.tar.gz
fix bug #40459 - make all stream funcs that create object call ctor
-rw-r--r--ext/standard/tests/streams/bug40459.phpt103
-rw-r--r--main/streams/userspace.c197
2 files changed, 183 insertions, 117 deletions
diff --git a/ext/standard/tests/streams/bug40459.phpt b/ext/standard/tests/streams/bug40459.phpt
new file mode 100644
index 0000000000..8ee4363ed9
--- /dev/null
+++ b/ext/standard/tests/streams/bug40459.phpt
@@ -0,0 +1,103 @@
+--TEST--
+bug 40459 - Test whether the constructor of the user-space stream wrapper is called when stream functions are called
+--FILE--
+<?php
+// Test whether the constructor of the user-space stream wrapper is called when stream functions are called
+class testwrapper {
+ private $constructorCalled = false;
+ function __construct() {
+ $this->constructorCalled = true;
+ }
+
+ function stream_open($path, $mode, $options, &$opened_path)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return true;
+ }
+
+ function url_stat($url, $flags)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return array();
+ }
+
+ function unlink($url)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function rename($from, $to)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function mkdir($dir, $mode, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function rmdir($dir, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function dir_opendir($url, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return TRUE;
+ }
+ function stream_metadata()
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return TRUE;
+ }
+}
+
+stream_wrapper_register('test', 'testwrapper', STREAM_IS_URL);
+
+echo 'stream_open: ';
+fopen('test://test', 'r');
+echo "\n";
+
+echo 'url_stat: ';
+stat('test://test');
+echo "\n";
+
+echo 'dir_opendir: ';
+opendir('test://test');
+echo "\n";
+
+echo 'rmdir: ';
+rmdir('test://test');
+echo "\n";
+
+echo 'mkdir: ';
+mkdir('test://test');
+echo "\n";
+
+echo 'rename: ';
+rename('test://test', 'test://test2');
+echo "\n";
+
+echo 'unlink: ';
+unlink('test://test');
+echo "\n";
+
+echo 'touch: ';
+touch('test://test', time());
+echo "\n";
+
+
+
+?>
+==DONE==
+--EXPECT--
+stream_open: yes
+url_stat: yes
+dir_opendir: yes
+rmdir: yes
+mkdir: yes
+rename: yes
+unlink: yes
+touch: yes
+==DONE==
diff --git a/main/streams/userspace.c b/main/streams/userspace.c
index 96a5195ed3..3b277160d6 100644
--- a/main/streams/userspace.c
+++ b/main/streams/userspace.c
@@ -281,43 +281,22 @@ typedef struct _php_userstream_data php_userstream_data_t;
}}} **/
-static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+static zval *user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context TSRMLS_DC)
{
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- php_userstream_data_t *us;
- zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
- zval **args[4];
- int call_result;
- php_stream *stream = NULL;
- zend_bool old_in_user_include;
-
- /* Try to catch bad usage without preventing flexibility */
- if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
- return NULL;
- }
- FG(user_stream_current_filename) = filename;
+ zval *object;
+ /* create an instance of our class */
+ ALLOC_ZVAL(object);
+ object_init_ex(object, uwrap->ce);
+ Z_SET_REFCOUNT_P(object, 1);
+ Z_SET_ISREF_P(object);
- /* if the user stream was registered as local and we are in include context,
- we add allow_url_include restrictions to allow_url_fopen ones */
- /* we need only is_url == 0 here since if is_url == 1 and remote wrappers
- were restricted we wouldn't get here */
- old_in_user_include = PG(in_user_include);
- if(uwrap->wrapper.is_url == 0 &&
- (options & STREAM_OPEN_FOR_INCLUDE) &&
- !PG(allow_url_include)) {
- PG(in_user_include) = 1;
+ if (context) {
+ add_property_resource(object, "context", context->rsrc_id);
+ zend_list_addref(context->rsrc_id);
+ } else {
+ add_property_null(object, "context");
}
- us = emalloc(sizeof(*us));
- us->wrapper = uwrap;
-
- /* create an instance of our class */
- ALLOC_ZVAL(us->object);
- object_init_ex(us->object, uwrap->ce);
- Z_SET_REFCOUNT_P(us->object, 1);
- Z_SET_ISREF_P(us->object);
-
if (uwrap->ce->constructor) {
zend_fcall_info fci;
zend_fcall_info_cache fcc;
@@ -327,7 +306,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
fci.function_table = &uwrap->ce->function_table;
fci.function_name = NULL;
fci.symbol_table = NULL;
- fci.object_ptr = us->object;
+ fci.object_ptr = object;
fci.retval_ptr_ptr = &retval_ptr;
fci.param_count = 0;
fci.params = NULL;
@@ -336,16 +315,13 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
fcc.initialized = 1;
fcc.function_handler = uwrap->ce->constructor;
fcc.calling_scope = EG(scope);
- fcc.called_scope = Z_OBJCE_P(us->object);
- fcc.object_ptr = us->object;
+ fcc.called_scope = Z_OBJCE_P(object);
+ fcc.object_ptr = object;
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute %s::%s()", uwrap->ce->name, uwrap->ce->constructor->common.function_name);
- zval_dtor(us->object);
- FREE_ZVAL(us->object);
- efree(us);
- FG(user_stream_current_filename) = NULL;
- PG(in_user_include) = old_in_user_include;
+ zval_dtor(object);
+ FREE_ZVAL(object);
return NULL;
} else {
if (retval_ptr) {
@@ -353,12 +329,46 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
}
}
}
+ return object;
+}
- if (context) {
- add_property_resource(us->object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(us->object, "context");
+static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
+ php_userstream_data_t *us;
+ zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
+ zval **args[4];
+ int call_result;
+ php_stream *stream = NULL;
+ zend_bool old_in_user_include;
+
+ /* Try to catch bad usage without preventing flexibility */
+ if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
+ return NULL;
+ }
+ FG(user_stream_current_filename) = filename;
+
+ /* if the user stream was registered as local and we are in include context,
+ we add allow_url_include restrictions to allow_url_fopen ones */
+ /* we need only is_url == 0 here since if is_url == 1 and remote wrappers
+ were restricted we wouldn't get here */
+ old_in_user_include = PG(in_user_include);
+ if(uwrap->wrapper.is_url == 0 &&
+ (options & STREAM_OPEN_FOR_INCLUDE) &&
+ !PG(allow_url_include)) {
+ PG(in_user_include) = 1;
+ }
+
+ us = emalloc(sizeof(*us));
+ us->wrapper = uwrap;
+
+ us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(us->object == NULL) {
+ FG(user_stream_current_filename) = NULL;
+ PG(in_user_include) = old_in_user_include;
+ efree(us);
+ return NULL;
}
/* call it's stream_open method - set up params first */
@@ -447,17 +457,11 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
us = emalloc(sizeof(*us));
us->wrapper = uwrap;
- /* create an instance of our class */
- ALLOC_ZVAL(us->object);
- object_init_ex(us->object, uwrap->ce);
- Z_SET_REFCOUNT_P(us->object, 1);
- Z_SET_ISREF_P(us->object);
-
- if (context) {
- add_property_resource(us->object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(us->object, "context");
+ us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(us == NULL) {
+ FG(user_stream_current_filename) = NULL;
+ efree(us);
+ return NULL;
}
/* call it's dir_open method - set up params first */
@@ -1157,16 +1161,9 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the unlink method */
@@ -1211,16 +1208,9 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the rename method */
@@ -1270,16 +1260,9 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode,
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the mkdir method */
@@ -1335,16 +1318,9 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the rmdir method */
@@ -1420,16 +1396,10 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, char *url, int opt
}
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ zval_ptr_dtor(&zvalue);
+ return ret;
}
/* call the mkdir method */
@@ -1484,16 +1454,9 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int fla
int ret = -1;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call it's stat_url method - set up params first */