diff --git a/main/streams/userspace.c b/main/streams/userspace.c index f5e25aa96c77..146c81bf6058 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -88,7 +88,11 @@ PHP_MINIT_FUNCTION(user_streams) struct _php_userstream_data { struct php_user_stream_wrapper * wrapper; - zval object; + zend_object *object; + /* Caches for most frequently used methods */ + zend_function *fn_cache_read; + zend_function *fn_cache_eof; + zend_function *fn_cache_write; }; typedef struct _php_userstream_data php_userstream_data_t; @@ -249,36 +253,68 @@ typedef struct _php_userstream_data php_userstream_data_t; }}} **/ -static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object) +static zend_function *php_userstream_get_fn(php_userstream_data_t *us, zend_function **cache, const char *name, size_t len) +{ + if (cache && *cache) { + return *cache; + } + + zend_function *fn = zend_hash_str_find_ptr(&us->object->ce->function_table, name, len); + + if (cache) { + *cache = fn; + } + + return fn; +} + +static zend_result php_userstream_call(php_userstream_data_t *us, zend_function **cache, const char *name, size_t len, zval *retval, uint32_t param_count, zval *params) +{ + zend_function *fn = php_userstream_get_fn(us, cache, name, len); + if (UNEXPECTED(!fn || !(fn->common.fn_flags & ZEND_ACC_PUBLIC))) { // TODO: this path should be tested with magic methods via a .phpt file + /* Slow fallback */ + zend_string *tmp; + ALLOCA_FLAG(use_heap); + ZSTR_ALLOCA_INIT(tmp, name, len, use_heap); + zend_result result = zend_call_method_if_exists(us->object, tmp, retval, param_count, params); + ZSTR_ALLOCA_FREE(tmp, use_heap); + return result; + } else { + zend_call_known_instance_method(fn, us->object, retval, param_count, params); + return SUCCESS; + } +} + +static zend_object *user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context) { if (uwrap->ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { - ZVAL_UNDEF(object); - return; + return NULL; } /* create an instance of our class */ - if (object_init_ex(object, uwrap->ce) == FAILURE) { - ZVAL_UNDEF(object); - return; + zval zobj; + if (object_init_ex(&zobj, uwrap->ce) == FAILURE) { + return NULL; } if (context) { GC_ADDREF(context->res); - add_property_resource(object, "context", context->res); + add_property_resource(&zobj, "context", context->res); } else { - add_property_null(object, "context"); + add_property_null(&zobj, "context"); } if (EG(exception) != NULL) { - zval_ptr_dtor(object); - ZVAL_UNDEF(object); - return; + zval_ptr_dtor(&zobj); + return NULL; } if (uwrap->ce->constructor) { zend_call_known_instance_method_with_0_params( - uwrap->ce->constructor, Z_OBJ_P(object), NULL); + uwrap->ce->constructor, Z_OBJ(zobj), NULL); } + + return Z_OBJ(zobj); } static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, @@ -309,13 +345,13 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * PG(in_user_include) = 1; } - us = emalloc(sizeof(*us)); + us = ecalloc(1, sizeof(*us)); us->wrapper = uwrap; - /* zend_call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ + /* method call may unregister the stream wrapper. Hold on to it. */ GC_ADDREF(us->wrapper->resource); - user_stream_create_object(uwrap, context, &us->object); - if (Z_ISUNDEF(us->object)) { + us->object = user_stream_create_object(uwrap, context); + if (!us->object) { goto end; } @@ -325,9 +361,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * ZVAL_LONG(&args[2], options); ZVAL_NEW_REF(&args[3], &EG(uninitialized_zval)); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_OPEN, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &zretval, 4, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_OPEN), &zretval, 4, args); /* Keep arg3 alive if it has assigned the reference */ zval_ptr_dtor(&args[1]); @@ -355,7 +389,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * // TODO Warn when assigning a non string value to the reference? /* set wrapper data to be a reference to our object */ - ZVAL_COPY(&stream->wrapperdata, &us->object); + ZVAL_OBJ_COPY(&stream->wrapperdata, us->object); } else { php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_OPEN "\" call failed", ZSTR_VAL(us->wrapper->ce->name)); @@ -368,7 +402,9 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * FG(user_stream_current_filename) = NULL; PG(in_user_include) = old_in_user_include; if (stream == NULL) { - zval_ptr_dtor(&us->object); + if (us->object) { + OBJ_RELEASE(us->object); + } zend_list_delete(us->wrapper->resource); efree(us); } @@ -399,13 +435,13 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char } FG(user_stream_current_filename) = filename; - us = emalloc(sizeof(*us)); + us = ecalloc(1, sizeof(*us)); us->wrapper = uwrap; - /* zend_call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ + /* method call may unregister the stream wrapper. Hold on to it. */ GC_ADDREF(us->wrapper->resource); - user_stream_create_object(uwrap, context, &us->object); - if (Z_TYPE(us->object) == IS_UNDEF) { + us->object = user_stream_create_object(uwrap, context); + if (!us->object) { goto end; } @@ -413,9 +449,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char ZVAL_STRING(&args[0], filename); ZVAL_LONG(&args[1], options); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_OPEN, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &zretval, 2, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_DIR_OPEN), &zretval, 2, args); zval_ptr_dtor(&args[0]); if (UNEXPECTED(call_result == FAILURE)) { @@ -433,7 +467,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode); /* set wrapper data to be a reference to our object */ - ZVAL_COPY(&stream->wrapperdata, &us->object); + ZVAL_OBJ_COPY(&stream->wrapperdata, us->object); } else { php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed", ZSTR_VAL(us->wrapper->ce->name)); @@ -443,7 +477,9 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char end: FG(user_stream_current_filename) = NULL; if (stream == NULL) { - zval_ptr_dtor(&us->object); + if (us->object) { + OBJ_RELEASE(us->object); + } zend_list_delete(us->wrapper->resource); efree(us); } @@ -559,16 +595,14 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_ zval args[1]; ssize_t didwrite; - assert(us != NULL); + ZEND_ASSERT(us != NULL); ZVAL_STRINGL(&args[0], (char*)buf, count); uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_WRITE, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, &us->fn_cache_write, ZEND_STRL(USERSTREAM_WRITE), &retval, 1, args); zval_ptr_dtor(&args[0]); if (UNEXPECTED(call_result == FAILURE)) { @@ -609,15 +643,13 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count size_t didread = 0; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - assert(us != NULL); + ZEND_ASSERT(us != NULL); uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; ZVAL_LONG(&args[0], count); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_READ, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, &us->fn_cache_read, ZEND_STRL(USERSTREAM_READ), &retval, 1, args); if (UNEXPECTED(Z_ISUNDEF(retval))) { goto err; @@ -652,11 +684,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count ZVAL_UNDEF(&retval); /* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */ - - func_name = ZSTR_INIT_LITERAL(USERSTREAM_EOF, false); - call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); - + call_result = php_userstream_call(us, &us->fn_cache_eof, ZEND_STRL(USERSTREAM_EOF), &retval, 0, NULL); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF", @@ -690,16 +718,13 @@ static int php_userstreamop_close(php_stream *stream, int close_handle) zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - assert(us != NULL); + ZEND_ASSERT(us != NULL); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_CLOSE, false); - zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_CLOSE), &retval, 0, NULL); zval_ptr_dtor(&retval); - zval_ptr_dtor(&us->object); - ZVAL_UNDEF(&us->object); + OBJ_RELEASE(us->object); efree(us); @@ -711,13 +736,11 @@ static int php_userstreamop_flush(php_stream *stream) zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - assert(us != NULL); + ZEND_ASSERT(us != NULL); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_FLUSH, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_FLUSH), &retval, 0, NULL); - int ret = call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zend_is_true(&retval) ? 0 : -1; + int ret = Z_TYPE(retval) != IS_UNDEF && zend_is_true(&retval) ? 0 : -1; zval_ptr_dtor(&retval); @@ -731,7 +754,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; zval args[2]; - assert(us != NULL); + ZEND_ASSERT(us != NULL); ZVAL_LONG(&args[0], offset); ZVAL_LONG(&args[1], whence); @@ -739,10 +762,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_SEEK, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 2, args); - zend_string_release_ex(func_name, false); - + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_SEEK), &retval, 2, args); if (call_result == FAILURE) { /* stream_seek is not implemented, so disable seeks for this stream */ stream->flags |= PHP_STREAM_FLAG_NO_SEEK; @@ -766,9 +786,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when } /* now determine where we are */ - func_name = ZSTR_INIT_LITERAL(USERSTREAM_TELL, false); - call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_TELL), &retval, 0, NULL); if (call_result == SUCCESS && Z_TYPE(retval) == IS_LONG) { *newoffs = Z_LVAL(retval); @@ -833,10 +851,7 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb) php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; int ret = -1; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_STAT, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); - + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_STAT), &retval, 0, NULL); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!", ZSTR_VAL(us->wrapper->ce->name)); @@ -857,13 +872,11 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb) return ret; } -static int user_stream_set_check_liveliness(const php_userstream_data_t *us) +static int user_stream_set_check_liveliness(php_userstream_data_t *us) { zval retval; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_EOF, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_EOF), &retval, 0, NULL); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, @@ -885,7 +898,7 @@ static int user_stream_set_check_liveliness(const php_userstream_data_t *us) } } -static int user_stream_set_locking(const php_userstream_data_t *us, int value) +static int user_stream_set_locking(php_userstream_data_t *us, int value) { zval retval; zval zlock; @@ -911,9 +924,7 @@ static int user_stream_set_locking(const php_userstream_data_t *us, int value) ZVAL_LONG(&zlock, lock); /* TODO wouldblock */ - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_LOCK, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, &zlock); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_LOCK), &retval, 1, &zlock); if (UNEXPECTED(call_result == FAILURE)) { if (value == 0) { @@ -947,7 +958,7 @@ static int user_stream_set_truncation(const php_userstream_data_t *us, int value if (value == PHP_STREAM_TRUNCATE_SUPPORTED) { zval zstr; ZVAL_STR(&zstr, func_name); - bool is_callable = zend_is_callable_ex(&zstr, Z_OBJ(us->object), IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, NULL, NULL); + bool is_callable = zend_is_callable_ex(&zstr, us->object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, NULL, NULL); // Frees func_name zval_ptr_dtor(&zstr); return is_callable ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; @@ -965,7 +976,7 @@ static int user_stream_set_truncation(const php_userstream_data_t *us, int value zval size; ZVAL_LONG(&size, (zend_long)new_size); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, &size); + zend_result call_result = zend_call_method_if_exists(us->object, func_name, &retval, 1, &size); zend_string_release_ex(func_name, false); if (UNEXPECTED(call_result == FAILURE)) { @@ -988,7 +999,7 @@ static int user_stream_set_truncation(const php_userstream_data_t *us, int value } } -static int user_stream_set_option(const php_userstream_data_t *us, int option, int value, void *ptrparam) +static int user_stream_set_option(php_userstream_data_t *us, int option, int value, void *ptrparam) { zval args[3]; ZVAL_LONG(&args[0], option); @@ -1008,9 +1019,7 @@ static int user_stream_set_option(const php_userstream_data_t *us, int option, i } zval retval; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_SET_OPTION, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 3, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_SET_OPTION), &retval, 3, args); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, @@ -1063,12 +1072,11 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[1]; - zval object; int ret = 0; /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { return ret; } @@ -1077,10 +1085,10 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_UNLINK, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 1, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 1, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name)); @@ -1100,12 +1108,11 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[2]; - zval object; int ret = 0; /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { return ret; } @@ -1114,11 +1121,11 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from ZVAL_STRING(&args[1], url_to); zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_RENAME, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 2, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[1]); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name)); @@ -1138,12 +1145,11 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[3]; - zval object; int ret = 0; /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { return ret; } @@ -1153,10 +1159,10 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int ZVAL_LONG(&args[2], options); zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_MKDIR, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 3, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 3, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name)); @@ -1176,12 +1182,11 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[2]; - zval object; int ret = 0; /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { return ret; } @@ -1190,10 +1195,10 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, ZVAL_LONG(&args[1], options); zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_RMDIR, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 2, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name)); @@ -1213,7 +1218,6 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[3]; - zval object; int ret = 0; switch(option) { @@ -1240,8 +1244,8 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i } /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { zval_ptr_dtor(&args[2]); return ret; } @@ -1251,11 +1255,11 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i ZVAL_LONG(&args[1], option); zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_METADATA, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 3, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 3, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[2]); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name)); @@ -1276,12 +1280,11 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zretval; zval args[2]; - zval object; int ret = -1; /* create an instance of our class */ - user_stream_create_object(uwrap, context, &object); - if (Z_TYPE(object) == IS_UNDEF) { + zend_object *object = user_stream_create_object(uwrap, context); + if (!object) { return -1; } @@ -1290,10 +1293,10 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i ZVAL_LONG(&args[1], flags); zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_STATURL, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_result call_result = zend_call_method_if_exists(object, func_name, &zretval, 2, args); zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&object); + OBJ_RELEASE(object); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!", @@ -1327,9 +1330,7 @@ static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t co return -1; } - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_READ, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_DIR_READ), &retval, 0, NULL); if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!", @@ -1361,15 +1362,12 @@ static int php_userstreamop_closedir(php_stream *stream, int close_handle) zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - assert(us != NULL); + ZEND_ASSERT(us != NULL); - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_CLOSE, false); - zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_DIR_CLOSE), &retval, 0, NULL); zval_ptr_dtor(&retval); - zval_ptr_dtor(&us->object); - ZVAL_UNDEF(&us->object); + OBJ_RELEASE(us->object); efree(us); return 0; @@ -1380,9 +1378,7 @@ static int php_userstreamop_rewinddir(php_stream *stream, zend_off_t offset, int zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_REWIND, false); - zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); - zend_string_release_ex(func_name, false); + php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_DIR_REWIND), &retval, 0, NULL); zval_ptr_dtor(&retval); @@ -1412,9 +1408,7 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr) uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_CAST, false); - zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); - zend_string_release_ex(func_name, false); + zend_result call_result = php_userstream_call(us, NULL, ZEND_STRL(USERSTREAM_CAST), &retval, 1, args); if (UNEXPECTED(call_result == FAILURE)) { if (report_errors) {