diff --git a/NEWS b/NEWS index db10e1be45470..3732e9946db84 100644 --- a/NEWS +++ b/NEWS @@ -154,6 +154,7 @@ PHP NEWS - SimpleXML: . Fixed bug #75245 (Don't set content of elements with only whitespaces). (eriklundin) + . Fixed bug #63575 (Root elements are not properly cloned). (cmb) - sodium: . Fixed bug #77646 (sign_detached() strings not terminated). (Frank) diff --git a/UPGRADING b/UPGRADING index 794b91f9432f0..b7670f813be97 100644 --- a/UPGRADING +++ b/UPGRADING @@ -440,7 +440,7 @@ PHP 8.0 UPGRADE NOTES - Sysvmsg: . msg_get_queue() will now return an SysvMessageQueue object rather than a - resource. Return value checks using is_resource() should be replaced with + resource. Return value checks using is_resource() should be replaced with checks for `false`. - Sysvsem: @@ -474,6 +474,12 @@ PHP 8.0 UPGRADE NOTES - Zlib: . gzgetss() has been removed. + . inflate_init() will now return an InflateContext object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. + . deflate_init() will now return a DeflateContext object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. ======================================== 2. New Features diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 7c715e853bf5b..b0f913aac3e09 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -196,18 +196,9 @@ AC_ARG_ENABLE([zts], [ZEND_ZTS=$enableval], [ZEND_ZTS=no]) -AC_ARG_ENABLE([inline-optimization], - [AS_HELP_STRING([--disable-inline-optimization], - [If building zend_execute.lo fails, try this switch])], - [ZEND_INLINE_OPTIMIZATION=$enableval], - [ZEND_INLINE_OPTIMIZATION=yes]) - AC_MSG_CHECKING(whether to enable thread-safety) AC_MSG_RESULT($ZEND_ZTS) -AC_MSG_CHECKING(whether to enable inline optimization for GCC) -AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION) - AC_MSG_CHECKING(whether to enable Zend debugging) AC_MSG_RESULT($ZEND_DEBUG) @@ -232,18 +223,8 @@ if test "$ZEND_ZTS" = "yes"; then CFLAGS="$CFLAGS -DZTS" fi -changequote({,}) -if test -n "$GCC" && test "$ZEND_INLINE_OPTIMIZATION" != "yes"; then - INLINE_CFLAGS=`echo $ac_n "$CFLAGS $ac_c" | sed s/-O[0-9s]*//` -else - INLINE_CFLAGS="$CFLAGS" -fi -changequote([,]) - AC_C_INLINE -AC_SUBST(INLINE_CFLAGS) - AC_MSG_CHECKING(target system is Darwin) if echo "$target" | grep "darwin" > /dev/null; then AC_DEFINE([DARWIN], 1, [Define if the target system is darwin]) diff --git a/Zend/zend.c b/Zend/zend.c index f7f293704a53d..ae05ed3f36241 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -166,7 +166,7 @@ ZEND_INI_BEGIN() ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding) STD_ZEND_INI_BOOLEAN("zend.detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals) #ifdef ZEND_SIGNALS - STD_ZEND_INI_BOOLEAN("zend.signal_check", "0", ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals) + STD_ZEND_INI_BOOLEAN("zend.signal_check", ZEND_DEBUG ? "1" : "0", ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals) #endif STD_ZEND_INI_BOOLEAN("zend.exception_ignore_args", "0", ZEND_INI_ALL, OnUpdateBool, exception_ignore_args, zend_executor_globals, executor_globals) ZEND_INI_END() diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 8ed0e20871c7f..bdcdfaea318f4 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -716,6 +716,7 @@ END_EXTERN_C() #define RETVAL_ARR(r) ZVAL_ARR(return_value, r) #define RETVAL_EMPTY_ARRAY() ZVAL_EMPTY_ARRAY(return_value) #define RETVAL_OBJ(r) ZVAL_OBJ(return_value, r) +#define RETVAL_OBJ_COPY(r) ZVAL_OBJ_COPY(return_value, r) #define RETVAL_COPY(zv) ZVAL_COPY(return_value, zv) #define RETVAL_COPY_VALUE(zv) ZVAL_COPY_VALUE(return_value, zv) #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor) @@ -740,6 +741,7 @@ END_EXTERN_C() #define RETURN_ARR(r) do { RETVAL_ARR(r); return; } while (0) #define RETURN_EMPTY_ARRAY() do { RETVAL_EMPTY_ARRAY(); return; } while (0) #define RETURN_OBJ(r) do { RETVAL_OBJ(r); return; } while (0) +#define RETURN_OBJ_COPY(r) do { RETVAL_OBJ_COPY(r); return; } while (0) #define RETURN_COPY(zv) do { RETVAL_COPY(zv); return; } while (0) #define RETURN_COPY_VALUE(zv) do { RETVAL_COPY_VALUE(zv); return; } while (0) #define RETURN_ZVAL(zv, copy, dtor) do { RETVAL_ZVAL(zv, copy, dtor); return; } while (0) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 775bab1504a3f..521c2c32de199 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -2069,9 +2069,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp); if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) { - ZVAL_OBJ(&tmp, object); + ZVAL_OBJ_COPY(&tmp, object); zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp); - Z_ADDREF(tmp); } ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR)); diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index af008c3628fa5..40ebaae0ab74d 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -283,8 +283,7 @@ static int zend_create_closure_from_callable(zval *return_value, zval *callable, /* For Closure::fromCallable([$closure, "__invoke"]) return $closure. */ if (fcc.object && fcc.object->ce == zend_ce_closure && zend_string_equals_literal(mptr->common.function_name, "__invoke")) { - ZVAL_OBJ(return_value, fcc.object); - GC_ADDREF(fcc.object); + RETVAL_OBJ_COPY(fcc.object); zend_free_trampoline(mptr); return SUCCESS; } @@ -725,8 +724,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent if (scope) { closure->func.common.fn_flags |= ZEND_ACC_PUBLIC; if (this_ptr && Z_TYPE_P(this_ptr) == IS_OBJECT && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) { - Z_ADDREF_P(this_ptr); - ZVAL_OBJ(&closure->this_ptr, Z_OBJ_P(this_ptr)); + ZVAL_OBJ_COPY(&closure->this_ptr, Z_OBJ_P(this_ptr)); } } } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 062ed8b025916..a34b1d8bea99b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5906,7 +5906,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall zend_op_array *op_array = CG(active_op_array); zend_class_entry *scope = op_array->scope; zend_bool is_ctor = - scope && zend_string_equals_literal_ci(op_array->function_name, "__construct"); + scope && zend_is_constructor(op_array->function_name); if (!is_ctor) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare promoted property outside a constructor"); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a74ae530b1bbc..803627f9a1d19 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -1120,8 +1120,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob zend_iterator_init(iterator); iterator->funcs = &zend_generator_iterator_functions; - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->data, Z_OBJ_P(object)); return iterator; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index b6a3a891b23ca..7cee42085bf58 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -2416,8 +2416,7 @@ static void check_unrecoverable_load_failure(zend_class_entry *ce) { zend_string *exception_str; zval exception_zv; ZEND_ASSERT(EG(exception) && "Exception must have been thrown"); - ZVAL_OBJ(&exception_zv, EG(exception)); - Z_ADDREF(exception_zv); + ZVAL_OBJ_COPY(&exception_zv, EG(exception)); zend_clear_exception(); exception_str = zval_get_string(&exception_zv); zend_error_noreturn(E_ERROR, diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 52d3a8ee19e37..6ac2721f453d5 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -211,8 +211,7 @@ static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zva zend_iterator_init((zend_object_iterator*)iterator); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->it.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->it.data, Z_OBJ_P(object)); iterator->it.funcs = &zend_interface_iterator_funcs_iterator; iterator->ce = Z_OBJCE_P(object); ZVAL_UNDEF(&iterator->value); diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c index 96870f8d5cc49..e69914752aca1 100644 --- a/Zend/zend_signal.c +++ b/Zend/zend_signal.c @@ -328,7 +328,6 @@ void zend_signal_activate(void) SIGG(active) = 1; SIGG(depth) = 0; - SIGG(check) = ZEND_DEBUG; } /* }}} */ /* {{{ zend_signal_deactivate diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 10a751d1b4f2c..7796979ed842f 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -968,6 +968,14 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { Z_TYPE_INFO_P(__z) = IS_OBJECT_EX; \ } while (0) +#define ZVAL_OBJ_COPY(z, o) do { \ + zval *__z = (z); \ + zend_object *__o = (o); \ + GC_ADDREF(__o); \ + Z_OBJ_P(__z) = __o; \ + Z_TYPE_INFO_P(__z) = IS_OBJECT_EX; \ + } while (0) + #define ZVAL_RES(z, r) do { \ zval *__z = (z); \ Z_RES_P(__z) = (r); \ diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index db5ffde2fdcf1..b633a57e9fd5e 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -189,8 +189,7 @@ static zend_always_inline zend_bool zend_weakref_find(zval *referent, zval *retu zend_weakref *wr; found_weakref: wr = ptr; - GC_ADDREF(&wr->std); - ZVAL_OBJ(return_value, &wr->std); + RETVAL_OBJ_COPY(&wr->std); return 1; } @@ -221,8 +220,7 @@ static zend_always_inline void zend_weakref_get(zval *weakref, zval *return_valu zend_weakref *wr = zend_weakref_fetch(weakref); if (wr->referent) { - ZVAL_OBJ(return_value, wr->referent); - Z_ADDREF_P(return_value); + RETVAL_OBJ_COPY(wr->referent); } } @@ -433,8 +431,7 @@ static HashTable *zend_weakmap_get_properties_for(zend_object *object, zend_prop zval obj_zv; array_init(&pair); - ZVAL_OBJ(&obj_zv, (zend_object *) obj_addr); - Z_ADDREF(obj_zv); + ZVAL_OBJ_COPY(&obj_zv, (zend_object *) obj_addr); add_assoc_zval(&pair, "key", &obj_zv); Z_TRY_ADDREF_P(val); add_assoc_zval(&pair, "value", val); @@ -511,8 +508,7 @@ static void zend_weakmap_iterator_get_current_key(zend_object_iterator *obj_iter ZEND_ASSERT(0 && "Must have integer key"); } - ZVAL_OBJ(key, (zend_object *) num_key); - Z_ADDREF_P(key); + ZVAL_OBJ_COPY(key, (zend_object *) num_key); } static void zend_weakmap_iterator_move_forward(zend_object_iterator *obj_iter) diff --git a/configure.ac b/configure.ac index 4f291b45d6282..ded516b01f095 100644 --- a/configure.ac +++ b/configure.ac @@ -1371,7 +1371,6 @@ old_CC=$CC if test "$PHP_THREAD_SAFETY" = "yes" && test -n "$ac_cv_pthreads_cflags"; then CXXFLAGS="$CXXFLAGS $ac_cv_pthreads_cflags" - INLINE_CFLAGS="$INLINE_CFLAGS $ac_cv_pthreads_cflags" CPPFLAGS="$CPPFLAGS $ac_cv_pthreads_cflags" fi @@ -1425,7 +1424,6 @@ PHP_CONFIGURE_PART(Generating files) CXXFLAGS_CLEAN=$CXXFLAGS CFLAGS_CLEAN="$CFLAGS \$(PROF_FLAGS)" CFLAGS="\$(CFLAGS_CLEAN) $standard_libtool_flag" -INLINE_CFLAGS="$INLINE_CFLAGS $standard_libtool_flag" CXXFLAGS="$CXXFLAGS $standard_libtool_flag \$(PROF_FLAGS)" if test "$PHP_PHAR" != "no" && test "$PHP_CLI" != "no"; then @@ -1470,7 +1468,7 @@ PHP_ADD_SOURCES(Zend, \ zend_execute_API.c zend_highlight.c zend_llist.c \ zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ - zend_list.c zend_builtin_functions.c zend_attributes.c \ + zend_list.c zend_builtin_functions.c zend_attributes.c zend_execute.c \ zend_ini.c zend_sort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \ zend_closures.c zend_weakrefs.c zend_float.c zend_string.c zend_signal.c zend_generators.c \ @@ -1478,16 +1476,6 @@ PHP_ADD_SOURCES(Zend, \ zend_default_classes.c zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_gdb.c, \ -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) -dnl Selectively disable optimization due to high RAM usage during compiling the -dnl executor. -if test -n "$GCC" && test "$ZEND_INLINE_OPTIMIZATION" != "yes"; then - flag=-O0 -else - flag= -fi - -PHP_ADD_SOURCES_X(Zend, zend_execute.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,PHP_GLOBAL_OBJS,,$flag) - PHP_ADD_BUILD_DIR(main main/streams) PHP_ADD_BUILD_DIR(TSRM) PHP_ADD_BUILD_DIR(Zend) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index a908fed2c7a22..94e8ab50c7124 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1542,8 +1542,7 @@ zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval zend_iterator_init((zend_object_iterator*)iterator); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &date_period_it_funcs; iterator->object = Z_PHPPERIOD_P(object); ZVAL_UNDEF(&iterator->current); @@ -2891,8 +2890,7 @@ PHP_FUNCTION(date_modify) RETURN_FALSE; } - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -2915,7 +2913,7 @@ PHP_METHOD(DateTimeImmutable, modify) RETURN_FALSE; } - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -2948,8 +2946,7 @@ PHP_FUNCTION(date_add) php_date_add(object, interval, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -2967,7 +2964,7 @@ PHP_METHOD(DateTimeImmutable, add) date_clone_immutable(object, &new_object); php_date_add(&new_object, interval, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3005,8 +3002,7 @@ PHP_FUNCTION(date_sub) php_date_sub(object, interval, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3024,7 +3020,7 @@ PHP_METHOD(DateTimeImmutable, sub) date_clone_immutable(object, &new_object); php_date_sub(&new_object, interval, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3109,8 +3105,7 @@ PHP_FUNCTION(date_timezone_set) php_date_timezone_set(object, timezone_object, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3129,7 +3124,7 @@ PHP_METHOD(DateTimeImmutable, setTimezone) date_clone_immutable(object, &new_object); php_date_timezone_set(&new_object, timezone_object, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3196,8 +3191,7 @@ PHP_FUNCTION(date_time_set) php_date_time_set(object, h, i, s, ms, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3216,7 +3210,7 @@ PHP_METHOD(DateTimeImmutable, setTime) date_clone_immutable(object, &new_object); php_date_time_set(&new_object, h, i, s, ms, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3246,8 +3240,7 @@ PHP_FUNCTION(date_date_set) php_date_date_set(object, y, m, d, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3266,7 +3259,7 @@ PHP_METHOD(DateTimeImmutable, setDate) date_clone_immutable(object, &new_object); php_date_date_set(&new_object, y, m, d, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3300,8 +3293,7 @@ PHP_FUNCTION(date_isodate_set) php_date_isodate_set(object, y, w, d, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3320,7 +3312,7 @@ PHP_METHOD(DateTimeImmutable, setISODate) date_clone_immutable(object, &new_object); php_date_isodate_set(&new_object, y, w, d, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ @@ -3349,8 +3341,7 @@ PHP_FUNCTION(date_timestamp_set) php_date_timestamp_set(object, timestamp, return_value); - Z_ADDREF_P(object); - ZVAL_OBJ(return_value, Z_OBJ_P(object)); + RETURN_OBJ_COPY(Z_OBJ_P(object)); } /* }}} */ @@ -3369,7 +3360,7 @@ PHP_METHOD(DateTimeImmutable, setTimestamp) date_clone_immutable(object, &new_object); php_date_timestamp_set(&new_object, timestamp, return_value); - ZVAL_OBJ(return_value, Z_OBJ(new_object)); + RETURN_OBJ(Z_OBJ(new_object)); } /* }}} */ diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index bd83114bd9f06..c21cc92154bbb 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -270,8 +270,7 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i iterator = emalloc(sizeof(php_dom_iterator)); zend_iterator_init(&iterator->intern); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &php_dom_iterator_funcs; ZVAL_UNDEF(&iterator->curobj); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 9dc50ac28773d..c90475df1af2d 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -997,8 +997,7 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml ZEND_ASSERT(basenode != NULL); - ZVAL_OBJ(&mapptr->baseobj_zv, &basenode->std); - Z_ADDREF(mapptr->baseobj_zv); + ZVAL_OBJ_COPY(&mapptr->baseobj_zv, &basenode->std); mapptr->baseobj = basenode; mapptr->nodetype = ntype; @@ -1136,8 +1135,7 @@ PHP_DOM_EXPORT zend_bool php_dom_create_object(xmlNodePtr obj, zval *return_valu } if ((intern = (dom_object *) php_dom_object_get_data((void *) obj))) { - GC_ADDREF(&intern->std); - ZVAL_OBJ(return_value, &intern->std); + ZVAL_OBJ_COPY(return_value, &intern->std); return 1; } diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index c55d9a2d94b16..7c955a5ecb232 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -110,8 +110,7 @@ U_CFUNC zend_object_iterator *_breakiterator_get_iterator( zoi_with_current *zoi_iter = static_cast(emalloc(sizeof *zoi_iter)); zend_iterator_init(&zoi_iter->zoi); - Z_ADDREF_P(object); - ZVAL_OBJ(&zoi_iter->zoi.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&zoi_iter->zoi.data, Z_OBJ_P(object)); zoi_iter->zoi.funcs = &breakiterator_iterator_funcs; zoi_iter->zoi.index = 0; zoi_iter->destroy_it = _breakiterator_destroy_it; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 769fe25f9d832..e1d8c5b92ca33 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -535,8 +535,7 @@ PHP_METHOD(PDO, prepare) stmt->default_fetch_type = dbh->default_fetch_type; stmt->dbh = dbh; /* give it a reference to me */ - ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std); - Z_ADDREF(stmt->database_object_handle); + ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std); /* we haven't created a lazy object yet */ ZVAL_UNDEF(&stmt->lazy_object_ref); @@ -1073,8 +1072,7 @@ PHP_METHOD(PDO, query) stmt->active_query_stringlen = statement_len; stmt->dbh = dbh; /* give it a reference to me */ - ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std); - Z_ADDREF(stmt->database_object_handle); + ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std); /* we haven't created a lazy object yet */ ZVAL_UNDEF(&stmt->lazy_object_ref); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index d273e1d519c22..881ce96cf63be 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -2473,7 +2473,7 @@ PHP_METHOD(Phar, convertToExecutable) phar_obj->archive->is_data = is_data; if (ret) { - ZVAL_OBJ(return_value, ret); + RETURN_OBJ(ret); } else { RETURN_NULL(); } @@ -2576,7 +2576,7 @@ PHP_METHOD(Phar, convertToData) phar_obj->archive->is_data = is_data; if (ret) { - ZVAL_OBJ(return_value, ret); + RETURN_OBJ(ret); } else { RETURN_NULL(); } @@ -3279,7 +3279,7 @@ PHP_METHOD(Phar, compress) } if (ret) { - ZVAL_OBJ(return_value, ret); + RETURN_OBJ(ret); } else { RETURN_NULL(); } @@ -3319,7 +3319,7 @@ PHP_METHOD(Phar, decompress) } if (ret) { - ZVAL_OBJ(return_value, ret); + RETURN_OBJ(ret); } else { RETURN_NULL(); } diff --git a/ext/readline/tests/libedit_callback_handler_install_001.phpt b/ext/readline/tests/libedit_callback_handler_install_001.phpt index c4cfced6278e9..70351fd74b615 100644 --- a/ext/readline/tests/libedit_callback_handler_install_001.phpt +++ b/ext/readline/tests/libedit_callback_handler_install_001.phpt @@ -4,6 +4,8 @@ readline_callback_handler_install(): Basic test +--INI-- +zend.signal_check=0 --FILE-- +--INI-- +zend.signal_check=0 --FILE-- ref_type = REF_TYPE_PARAMETER; intern->ce = fptr->common.scope; if (closure_object) { - Z_ADDREF_P(closure_object); - ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object)); + ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object)); } prop_name = reflection_prop_name(object); @@ -1343,8 +1342,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o intern->ref_type = REF_TYPE_FUNCTION; intern->ce = NULL; if (closure_object) { - Z_ADDREF_P(closure_object); - ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object)); + ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object)); } ZVAL_STR_COPY(reflection_prop_name(object), function->common.function_name); } @@ -1361,8 +1359,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho intern->ref_type = REF_TYPE_FUNCTION; intern->ce = ce; if (closure_object) { - Z_ADDREF_P(closure_object); - ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object)); + ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object)); } ZVAL_STR_COPY(reflection_prop_name(object), method->common.function_name); @@ -1490,7 +1487,6 @@ ZEND_METHOD(ReflectionFunction, __construct) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) { fptr = (zend_function*)zend_get_closure_method_def(closure); - Z_ADDREF_P(closure); } else { ALLOCA_FLAG(use_heap) @@ -1521,7 +1517,7 @@ ZEND_METHOD(ReflectionFunction, __construct) intern->ptr = fptr; intern->ref_type = REF_TYPE_FUNCTION; if (closure) { - ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure)); + ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure)); } else { ZVAL_UNDEF(&intern->obj); } @@ -1591,8 +1587,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis) if (!Z_ISUNDEF(intern->obj)) { closure_this = zend_get_closure_this_ptr(&intern->obj); if (!Z_ISUNDEF_P(closure_this)) { - Z_ADDREF_P(closure_this); - ZVAL_OBJ(return_value, Z_OBJ_P(closure_this)); + RETURN_OBJ_COPY(Z_OBJ_P(closure_this)); } } } @@ -1632,8 +1627,7 @@ ZEND_METHOD(ReflectionFunction, getClosure) if (!Z_ISUNDEF(intern->obj)) { /* Closures are immutable objects */ - Z_ADDREF(intern->obj); - ZVAL_OBJ(return_value, Z_OBJ(intern->obj)); + RETURN_OBJ_COPY(Z_OBJ(intern->obj)); } else { zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL); } @@ -2100,8 +2094,7 @@ ZEND_METHOD(ReflectionGenerator, __construct) } intern->ref_type = REF_TYPE_GENERATOR; - Z_ADDREF_P(generator); - ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator)); + ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(generator)); intern->ce = zend_ce_generator; } /* }}} */ @@ -2217,10 +2210,9 @@ ZEND_METHOD(ReflectionGenerator, getThis) REFLECTION_CHECK_VALID_GENERATOR(ex) if (Z_TYPE(ex->This) == IS_OBJECT) { - Z_ADDREF(ex->This); - ZVAL_OBJ(return_value, Z_OBJ(ex->This)); + RETURN_OBJ_COPY(Z_OBJ(ex->This)); } else { - ZVAL_NULL(return_value); + RETURN_NULL(); } } /* }}} */ @@ -2239,9 +2231,7 @@ ZEND_METHOD(ReflectionGenerator, getExecutingGenerator) REFLECTION_CHECK_VALID_GENERATOR(ex) current = zend_generator_get_current(generator); - GC_ADDREF(¤t->std); - - ZVAL_OBJ(return_value, (zend_object *) current); + RETURN_OBJ_COPY(¤t->std); } /* }}} */ @@ -3166,8 +3156,7 @@ ZEND_METHOD(ReflectionMethod, getClosure) if (Z_OBJCE_P(obj) == zend_ce_closure && (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { - Z_ADDREF_P(obj); - ZVAL_OBJ(return_value, Z_OBJ_P(obj)); + RETURN_OBJ_COPY(Z_OBJ_P(obj)); } else { zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj); } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 85372cb53deea..8d8a47f73ebba 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2035,12 +2035,20 @@ sxe_object_clone(zend_object *object) php_sxe_object *clone; xmlNodePtr nodep = NULL; xmlDocPtr docp = NULL; + zend_bool is_root_element = sxe->node && sxe->node->node && sxe->node->node->parent + && (sxe->node->node->parent->type == XML_DOCUMENT_NODE || sxe->node->node->parent->type == XML_HTML_DOCUMENT_NODE); clone = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count); - clone->document = sxe->document; - if (clone->document) { - clone->document->refcount++; - docp = clone->document->ptr; + + if (is_root_element) { + docp = xmlCopyDoc(sxe->document->ptr, 1); + php_libxml_increment_doc_ref((php_libxml_node_object *)clone, docp); + } else { + clone->document = sxe->document; + if (clone->document) { + clone->document->refcount++; + docp = clone->document->ptr; + } } clone->iter.isprefix = sxe->iter.isprefix; @@ -2053,7 +2061,11 @@ sxe_object_clone(zend_object *object) clone->iter.type = sxe->iter.type; if (sxe->node) { - nodep = xmlDocCopyNode(sxe->node->node, docp, 1); + if (is_root_element) { + nodep = xmlDocGetRootElement(docp); + } else { + nodep = xmlDocCopyNode(sxe->node->node, docp, 1); + } } php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL); @@ -2216,7 +2228,7 @@ PHP_FUNCTION(simplexml_load_file) php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL); - ZVAL_OBJ(return_value, &sxe->zo); + RETURN_OBJ(&sxe->zo); } /* }}} */ @@ -2270,7 +2282,7 @@ PHP_FUNCTION(simplexml_load_string) php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL); - ZVAL_OBJ(return_value, &sxe->zo); + RETURN_OBJ(&sxe->zo); } /* }}} */ @@ -2419,8 +2431,7 @@ zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, i iterator = emalloc(sizeof(php_sxe_iterator)); zend_iterator_init(&iterator->intern); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &php_sxe_iterator_funcs; iterator->sxe = Z_SXEOBJ_P(object); @@ -2568,7 +2579,7 @@ PHP_FUNCTION(simplexml_import_dom) php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL); - ZVAL_OBJ(return_value, &sxe->zo); + RETURN_OBJ(&sxe->zo); } else { php_error_docref(NULL, E_WARNING, "Invalid Nodetype to import"); RETVAL_NULL(); diff --git a/ext/simplexml/tests/bug39662.phpt b/ext/simplexml/tests/bug39662.phpt index 5dc2b99a92481..343aeef7036fd 100644 --- a/ext/simplexml/tests/bug39662.phpt +++ b/ext/simplexml/tests/bug39662.phpt @@ -23,7 +23,9 @@ object(SimpleXMLElement)#%d (0) { } object(SimpleXMLElement)#%d (0) { } -string(15) " +string(%d) " + -" + +" Done diff --git a/ext/simplexml/tests/bug63575.phpt b/ext/simplexml/tests/bug63575.phpt new file mode 100644 index 0000000000000..0947ea677de03 --- /dev/null +++ b/ext/simplexml/tests/bug63575.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #63575 (Root elements are not properly cloned) +--SKIPIF-- + +--FILE-- +'; + +$o1 = new SimpleXMlElement($xml); +$o2 = clone $o1; + +$r = current($o2->xpath('/a')); +$r->addChild('c', new SimpleXMlElement('')); + +echo $o1->asXML(), PHP_EOL, $o2->asXML(); +?> +--EXPECT-- + + + + + diff --git a/ext/soap/soap.c b/ext/soap/soap.c index d2ac5ea662701..6356ac73790c1 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1049,8 +1049,7 @@ PHP_METHOD(SoapServer, setObject) service->type = SOAP_OBJECT; - Z_ADDREF_P(obj); - ZVAL_OBJ(&service->soap_object, Z_OBJ_P(obj)); + ZVAL_OBJ_COPY(&service->soap_object, Z_OBJ_P(obj)); SOAP_SERVER_END_CODE(); } @@ -1760,8 +1759,7 @@ PHP_METHOD(SoapServer, addSoapHeader) *p = emalloc(sizeof(soapHeader)); memset(*p, 0, sizeof(soapHeader)); ZVAL_NULL(&(*p)->function_name); - Z_ADDREF_P(fault); - ZVAL_OBJ(&(*p)->retval, Z_OBJ_P(fault)); + ZVAL_OBJ_COPY(&(*p)->retval, Z_OBJ_P(fault)); SOAP_SERVER_END_CODE(); } diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index ced58ab20d599..e2b361fb5b04e 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -609,8 +609,7 @@ PHP_FUNCTION(spl_autoload_functions) ZEND_HASH_FOREACH_PTR(SPL_G(autoload_functions), alfi) { if (alfi->closure) { zval obj_zv; - ZVAL_OBJ(&obj_zv, alfi->closure); - Z_ADDREF(obj_zv); + ZVAL_OBJ_COPY(&obj_zv, alfi->closure); add_next_index_zval(return_value, &obj_zv); } else if (alfi->func_ptr->common.scope) { zval tmp; @@ -618,8 +617,7 @@ PHP_FUNCTION(spl_autoload_functions) array_init(&tmp); if (alfi->obj) { zval obj_zv; - ZVAL_OBJ(&obj_zv, alfi->obj); - Z_ADDREF(obj_zv); + ZVAL_OBJ_COPY(&obj_zv, alfi->obj); add_next_index_zval(&tmp, &obj_zv); } else { add_next_index_str(&tmp, zend_string_copy(alfi->ce->name)); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index ab263b6195f6c..86a1ad501c288 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -189,13 +189,11 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o zend_array_dup(spl_array_get_hash_table(other))); } else { ZEND_ASSERT(orig->handlers == &spl_handler_ArrayIterator); - GC_ADDREF(orig); - ZVAL_OBJ(&intern->array, orig); + ZVAL_OBJ_COPY(&intern->array, orig); intern->ar_flags |= SPL_ARRAY_USE_OTHER; } } else { - GC_ADDREF(orig); - ZVAL_OBJ(&intern->array, orig); + ZVAL_OBJ_COPY(&intern->array, orig); intern->ar_flags |= SPL_ARRAY_USE_OTHER; } } else { @@ -1173,8 +1171,7 @@ zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, zend_iterator_init(&iterator->it); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->it.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->it.data, Z_OBJ_P(object)); iterator->it.funcs = &spl_array_it_funcs; iterator->ce = ce; ZVAL_UNDEF(&iterator->value); @@ -1333,7 +1330,7 @@ PHP_METHOD(ArrayObject, getIterator) RETURN_THROWS(); } - ZVAL_OBJ(return_value, spl_array_object_new_ex(intern->ce_get_iterator, Z_OBJ_P(object), 0)); + RETURN_OBJ(spl_array_object_new_ex(intern->ce_get_iterator, Z_OBJ_P(object), 0)); } /* }}} */ @@ -1652,9 +1649,7 @@ PHP_METHOD(RecursiveArrayIterator, getChildren) return; } if (instanceof_function(Z_OBJCE_P(entry), Z_OBJCE_P(ZEND_THIS))) { - ZVAL_OBJ(return_value, Z_OBJ_P(entry)); - Z_ADDREF_P(return_value); - return; + RETURN_OBJ_COPY(Z_OBJ_P(entry)); } } diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index df33ae6548d8b..f30d7fcf7f78f 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -457,7 +457,7 @@ static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_o zend_update_class_constants(ce); intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); - ZVAL_OBJ(return_value, &intern->std); + RETVAL_OBJ(&intern->std); if (ce->constructor->common.scope != spl_ce_SplFileInfo) { ZVAL_STRINGL(&arg1, file_path, file_path_len); @@ -501,7 +501,7 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp } intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); - ZVAL_OBJ(return_value, &intern->std); + RETVAL_OBJ(&intern->std); spl_filesystem_object_get_file_name(source); if (ce->constructor->common.scope != spl_ce_SplFileInfo) { @@ -536,7 +536,7 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); - ZVAL_OBJ(return_value, &intern->std); + RETVAL_OBJ(&intern->std); spl_filesystem_object_get_file_name(source); @@ -802,8 +802,7 @@ PHP_METHOD(DirectoryIterator, current) if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } - ZVAL_OBJ(return_value, Z_OBJ_P(ZEND_THIS)); - Z_ADDREF_P(return_value); + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); } /* }}} */ @@ -1099,8 +1098,7 @@ PHP_METHOD(FilesystemIterator, current) spl_filesystem_object_get_file_name(intern); spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value); } else { - ZVAL_OBJ(return_value, Z_OBJ_P(ZEND_THIS)); - Z_ADDREF_P(return_value); + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); } } /* }}} */ @@ -1645,8 +1643,7 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval } dir_object = Z_SPLFILESYSTEM_P(object); iterator = spl_filesystem_object_to_iterator(dir_object); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &spl_filesystem_dir_it_funcs; /* ->current must be initialized; rewind doesn't set it and valid * doesn't check whether it's set */ @@ -1847,8 +1844,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva dir_object = Z_SPLFILESYSTEM_P(object); iterator = spl_filesystem_object_to_iterator(dir_object); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object)); iterator->intern.funcs = &spl_filesystem_tree_it_funcs; return &iterator->intern; diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 0462c46aa47cf..adf3d354cccd8 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1351,8 +1351,7 @@ zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object zend_iterator_init((zend_object_iterator*)iterator); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.it.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.it.data, Z_OBJ_P(object)); iterator->intern.it.funcs = &spl_dllist_it_funcs; iterator->intern.ce = ce; iterator->traverse_position = dllist_object->traverse_position; diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 2b86a85d5155d..63a3ef78fa286 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -980,8 +980,7 @@ zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *ob zend_iterator_init((zend_object_iterator*)iterator); - Z_ADDREF_P(object); - ZVAL_OBJ(&iterator->intern.it.data, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&iterator->intern.it.data, Z_OBJ_P(object)); iterator->intern.it.funcs = &spl_fixedarray_it_funcs; iterator->intern.ce = ce; ZVAL_UNDEF(&iterator->intern.value); diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index a6ccc855c0ef9..8ddd413cf3d90 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -459,8 +459,7 @@ static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zend_iterator_init((zend_object_iterator*)iterator); - Z_ADDREF_P(zobject); - ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(zobject)); + ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(zobject)); iterator->intern.funcs = &spl_recursive_it_iterator_funcs; return (zend_object_iterator*)iterator; } diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index c309d5d545e05..3102592238da9 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -534,8 +534,7 @@ PHP_METHOD(SQLite3, prepare) object_init_ex(return_value, php_sqlite3_stmt_entry); stmt_obj = Z_SQLITE3_STMT_P(return_value); stmt_obj->db_obj = db_obj; - Z_ADDREF_P(object); - ZVAL_OBJ(&stmt_obj->db_obj_zval, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&stmt_obj->db_obj_zval, Z_OBJ_P(object)); errcode = sqlite3_prepare_v2(db_obj->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &(stmt_obj->stmt), NULL); if (errcode != SQLITE_OK) { @@ -590,8 +589,7 @@ PHP_METHOD(SQLite3, query) object_init_ex(&stmt, php_sqlite3_stmt_entry); stmt_obj = Z_SQLITE3_STMT_P(&stmt); stmt_obj->db_obj = db_obj; - Z_ADDREF_P(object); - ZVAL_OBJ(&stmt_obj->db_obj_zval, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&stmt_obj->db_obj_zval, Z_OBJ_P(object)); return_code = sqlite3_prepare_v2(db_obj->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &(stmt_obj->stmt), NULL); if (return_code != SQLITE_OK) { @@ -1879,8 +1877,7 @@ PHP_METHOD(SQLite3Stmt, execute) result->is_prepared_statement = 1; result->db_obj = stmt_obj->db_obj; result->stmt_obj = stmt_obj; - Z_ADDREF_P(object); - ZVAL_OBJ(&result->stmt_obj_zval, Z_OBJ_P(object)); + ZVAL_OBJ_COPY(&result->stmt_obj_zval, Z_OBJ_P(object)); break; } @@ -1929,8 +1926,7 @@ PHP_METHOD(SQLite3Stmt, __construct) } stmt_obj->db_obj = db_obj; - Z_ADDREF_P(db_zval); - ZVAL_OBJ(&stmt_obj->db_obj_zval, Z_OBJ_P(db_zval)); + ZVAL_OBJ_COPY(&stmt_obj->db_obj_zval, Z_OBJ_P(db_zval)); errcode = sqlite3_prepare_v2(db_obj->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &(stmt_obj->stmt), NULL); if (errcode != SQLITE_OK) { diff --git a/ext/standard/array.c b/ext/standard/array.c index d942cfc184ce4..0a8484f99965c 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2479,8 +2479,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu } else if (zend_string_equals_literal(Z_STR_P(entry), "this")) { zend_object *object = zend_get_this_object(EG(current_execute_data)); if (object) { - GC_ADDREF(object); - ZVAL_OBJ(&data, object); + ZVAL_OBJ_COPY(&data, object); zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } } else { diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 0a429963bd59d..3c2c18db96802 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -757,7 +757,7 @@ PHP_FUNCTION(getenv) /* SAPI method returns an emalloc()'d string */ ptr = sapi_getenv(str, str_len); if (ptr) { - // TODO: avoid realocation ??? + // TODO: avoid reallocation ??? RETVAL_STRING(ptr); efree(ptr); return; @@ -775,7 +775,7 @@ PHP_FUNCTION(getenv) } SetLastError(0); - /*If the given bugger is not large enough to hold the data, the return value is + /*If the given buffer is not large enough to hold the data, the return value is the buffer size, in characters, required to hold the string and its terminating null character. We use this return value to alloc the final buffer. */ size = GetEnvironmentVariableW(keyw, &dummybuf, 0); diff --git a/ext/standard/var.c b/ext/standard/var.c index 5b4fd8fe54fd7..4d47e67e2c7d1 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -1001,8 +1001,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ zval *data; zend_ulong index; - Z_ADDREF_P(struc); - ZVAL_OBJ(&obj, Z_OBJ_P(struc)); + ZVAL_OBJ_COPY(&obj, Z_OBJ_P(struc)); if (php_var_serialize_call_magic_serialize(&retval, &obj) == FAILURE) { if (!EG(exception)) { smart_str_appendl(buf, "N;", 2); @@ -1065,8 +1064,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ if (ce != PHP_IC_ENTRY && zend_hash_str_exists(&ce->function_table, "__sleep", sizeof("__sleep")-1)) { zval retval, tmp; - Z_ADDREF_P(struc); - ZVAL_OBJ(&tmp, Z_OBJ_P(struc)); + ZVAL_OBJ_COPY(&tmp, Z_OBJ_P(struc)); if (php_var_serialize_call_sleep(&retval, &tmp) == FAILURE) { if (!EG(exception)) { diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 19d7238c46d61..f626dd1636781 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -1085,8 +1085,7 @@ PHP_FUNCTION(xml_set_object) parser = Z_XMLPARSER_P(pind); zval_ptr_dtor(&parser->object); - Z_ADDREF_P(mythis); - ZVAL_OBJ(&parser->object, Z_OBJ_P(mythis)); + ZVAL_OBJ_COPY(&parser->object, Z_OBJ_P(mythis)); RETVAL_TRUE; } diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h index b8f25015aecf5..6c43625217bc8 100644 --- a/ext/zlib/php_zlib.h +++ b/ext/zlib/php_zlib.h @@ -47,6 +47,7 @@ typedef struct _php_zlib_context { int status; size_t inflateDictlen; php_zlib_buffer buffer; + zend_object std; } php_zlib_context; ZEND_BEGIN_MODULE_GLOBALS(zlib) diff --git a/ext/zlib/tests/deflate_add_error.phpt b/ext/zlib/tests/deflate_add_error.phpt index b2b7d7917c0f0..4a467d39bfe98 100644 --- a/ext/zlib/tests/deflate_add_error.phpt +++ b/ext/zlib/tests/deflate_add_error.phpt @@ -27,5 +27,5 @@ try { ?> --EXPECT-- -deflate_add(): supplied resource is not a valid zlib deflate resource -Flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH +deflate_add(): Argument #1 ($context) must be of type DeflateContext, resource given +deflate_add(): Argument #3 ($flush_behavior) must be one of ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK, or ZLIB_FINISH diff --git a/ext/zlib/tests/deflate_init_error.phpt b/ext/zlib/tests/deflate_init_error.phpt index be3f0974d6526..b31a16be9accf 100644 --- a/ext/zlib/tests/deflate_init_error.phpt +++ b/ext/zlib/tests/deflate_init_error.phpt @@ -41,8 +41,8 @@ try { ?> --EXPECT-- -Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE -Compression level (42) must be within -1..9 -Compression level (-2) must be within -1..9 -Compression memory level (0) must be within 1..9 -Compression memory level (10) must be within 1..9 +deflate_init(): Argument #1 ($encoding) must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE +deflate_init(): "level" option must be between -1 and 9 +deflate_init(): "level" option must be between -1 and 9 +deflate_init(): "memory" option must be between 1 and 9 +deflate_init(): "memory" option must be between 1 and 9 diff --git a/ext/zlib/tests/dictionary_usage.phpt b/ext/zlib/tests/dictionary_usage.phpt index 195e9b216d5ac..359cfd3550eb4 100644 --- a/ext/zlib/tests/dictionary_usage.phpt +++ b/ext/zlib/tests/dictionary_usage.phpt @@ -18,7 +18,6 @@ var_dump($dictStr_a === $a); $r = inflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => $dict]); var_dump(inflate_add($r, $a, ZLIB_FINISH)); - $r = inflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => ["8"] + range("a", "z")]); var_dump(inflate_add($r, $a, ZLIB_FINISH)); diff --git a/ext/zlib/tests/inflate_add_error.phpt b/ext/zlib/tests/inflate_add_error.phpt index 9622e5a4c40b8..33792197523cd 100644 --- a/ext/zlib/tests/inflate_add_error.phpt +++ b/ext/zlib/tests/inflate_add_error.phpt @@ -26,5 +26,5 @@ try { ?> --EXPECT-- -inflate_add(): supplied resource is not a valid zlib inflate resource -Flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH +inflate_add(): Argument #1 ($context) must be of type InflateContext, resource given +inflate_add(): Argument #3 ($flush_mode) must be one of ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK, or ZLIB_FINISH diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index ae65ba439624b..aa3be3a513926 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -29,12 +29,13 @@ #include "ext/standard/php_string.h" #include "php_zlib.h" #include "zlib_arginfo.h" +#include "Zend/zend_interfaces.h" /* * zlib include files can define the following preprocessor defines which rename * the corresponding PHP functions to gzopen64, gzseek64 and gztell64 and thereby * breaking some software, most notably PEAR's Archive_Tar, which halts execution - * without error message on gzip compressed archivesa. + * without error message on gzip compressed archives. * * This only seems to happen on 32bit systems with large file support. */ @@ -42,45 +43,94 @@ #undef gzseek #undef gztell -int le_deflate; -#define le_deflate_name "zlib deflate" -int le_inflate; -#define le_inflate_name "zlib inflate" - ZEND_DECLARE_MODULE_GLOBALS(zlib) -/* {{{ Memory management wrappers */ +/* InflateContext class */ -static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size) -{ - return (voidpf)safe_emalloc(items, size, 0); +zend_class_entry *inflate_context_ce; +static zend_object_handlers inflate_context_object_handlers; + +static inline php_zlib_context *inflate_context_from_obj(zend_object *obj) { + return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); } -static void php_zlib_free(voidpf opaque, voidpf address) +#define Z_INFLATE_CONTEXT_P(zv) inflate_context_from_obj(Z_OBJ_P(zv)) + +static zend_object *inflate_context_create_object(zend_class_entry *class_type) { + php_zlib_context *intern = zend_object_alloc(sizeof(php_zlib_context), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &inflate_context_object_handlers; + + return &intern->std; +} + +static zend_function *inflate_context_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct InflateContext, use inflate_init() instead"); + return NULL; +} + +static void inflate_context_free_obj(zend_object *object) { - efree((void*)address); + php_zlib_context *intern = inflate_context_from_obj(object); + + if (intern->inflateDict) { + efree(intern->inflateDict); + } + inflateEnd(&intern->Z); + + zend_object_std_dtor(&intern->std); } /* }}} */ -/* {{{ Incremental deflate/inflate resource destructors */ +/* DeflateContext class */ + +zend_class_entry *deflate_context_ce; +static zend_object_handlers deflate_context_object_handlers; + +static inline php_zlib_context *deflate_context_from_obj(zend_object *obj) { + return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); +} + +#define Z_DEFLATE_CONTEXT_P(zv) deflate_context_from_obj(Z_OBJ_P(zv)) + +static zend_object *deflate_context_create_object(zend_class_entry *class_type) { + php_zlib_context *intern = zend_object_alloc(sizeof(php_zlib_context), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &deflate_context_object_handlers; + + return &intern->std; +} -void deflate_rsrc_dtor(zend_resource *res) +static zend_function *deflate_context_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct DeflateContext, use deflate_init() instead"); + return NULL; +} + +static void deflate_context_free_obj(zend_object *object) { - z_stream *ctx = zend_fetch_resource(res, le_deflate_name, le_deflate); - deflateEnd(ctx); - efree(ctx); + php_zlib_context *intern = deflate_context_from_obj(object); + + deflateEnd(&intern->Z); + + zend_object_std_dtor(&intern->std); } +/* }}} */ + +/* {{{ Memory management wrappers */ -void inflate_rsrc_dtor(zend_resource *res) +static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size) { - z_stream *ctx = zend_fetch_resource(res, le_inflate_name, le_inflate); - if (((php_zlib_context *) ctx)->inflateDict) { - efree(((php_zlib_context *) ctx)->inflateDict); - } - inflateEnd(ctx); - efree(ctx); + return (voidpf)safe_emalloc(items, size, 0); } +static void php_zlib_free(voidpf opaque, voidpf address) +{ + efree((void*)address); +} /* }}} */ /* {{{ php_zlib_output_conflict_check() */ @@ -786,7 +836,7 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, } efree(strings); if (!EG(exception)) { - zend_value_error("Dictionary entries must be non-empty strings"); + zend_argument_value_error(2, "must not contain empty strings"); } return 0; } @@ -796,7 +846,7 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, efree(ptr); } while (--ptr >= strings); efree(strings); - zend_value_error("Dictionary entries must not contain a NULL-byte"); + zend_argument_value_error(2, "must not contain strings with null bytes"); return 0; } } @@ -826,11 +876,11 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, return 1; } -/* {{{ proto resource inflate_init(int encoding) +/* {{{ proto InflateContext inflate_init(int encoding) Initialize an incremental inflate context with the specified encoding */ PHP_FUNCTION(inflate_init) { - z_stream *ctx; + php_zlib_context *ctx; zend_long encoding, window = 15; char *dict = NULL; size_t dictlen = 0; @@ -850,7 +900,7 @@ PHP_FUNCTION(inflate_init) } if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_FALSE; + RETURN_THROWS(); } switch (encoding) { @@ -863,12 +913,14 @@ PHP_FUNCTION(inflate_init) RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(php_zlib_context)); - ctx->zalloc = php_zlib_alloc; - ctx->zfree = php_zlib_free; - ((php_zlib_context *) ctx)->inflateDict = dict; - ((php_zlib_context *) ctx)->inflateDictlen = dictlen; - ((php_zlib_context *) ctx)->status = Z_OK; + object_init_ex(return_value, inflate_context_ce); + ctx = Z_INFLATE_CONTEXT_P(return_value); + + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; + ctx->inflateDict = dict; + ctx->inflateDictlen = dictlen; + ctx->status = Z_OK; if (encoding < 0) { encoding += 15 - window; @@ -876,31 +928,29 @@ PHP_FUNCTION(inflate_init) encoding -= 15 - window; } - if (Z_OK == inflateInit2(ctx, encoding)) { - if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { - php_zlib_context *php_ctx = (php_zlib_context *) ctx; - switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) { - case Z_OK: - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; - break; - case Z_DATA_ERROR: - php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - RETURN_RES(zend_register_resource(ctx, le_inflate)); - } else { - efree(ctx); + if (inflateInit2(&ctx->Z, encoding) != Z_OK) { + zval_ptr_dtor(return_value); php_error_docref(NULL, E_WARNING, "Failed allocating zlib.inflate context"); RETURN_FALSE; } + + if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { + switch (inflateSetDictionary(&ctx->Z, (Bytef *) ctx->inflateDict, ctx->inflateDictlen)) { + case Z_OK: + efree(ctx->inflateDict); + ctx->inflateDict = NULL; + break; + case Z_DATA_ERROR: + php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); + efree(ctx->inflateDict); + ctx->inflateDict = NULL; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } /* }}} */ -/* {{{ proto string inflate_add(resource context, string encoded_data[, int flush_mode = ZLIB_SYNC_FLUSH]) +/* {{{ proto string inflate_add(InflateContext context, string encoded_data[, int flush_mode = ZLIB_SYNC_FLUSH]) Incrementally inflate encoded data in the specified context */ PHP_FUNCTION(inflate_add) { @@ -908,17 +958,15 @@ PHP_FUNCTION(inflate_add) char *in_buf; size_t in_len, buffer_used = 0, CHUNK_SIZE = 8192; zval *res; - z_stream *ctx; + php_zlib_context *ctx; zend_long flush_type = Z_SYNC_FLUSH; int status; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &res, inflate_context_ce, &in_buf, &in_len, &flush_type)) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); switch (flush_type) { case Z_NO_FLUSH: @@ -930,16 +978,15 @@ PHP_FUNCTION(inflate_add) break; default: - zend_value_error( - "Flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH"); + zend_argument_value_error(3, "must be one of ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK, or ZLIB_FINISH"); RETURN_THROWS(); } /* Lazy-resetting the zlib stream so ctx->total_in remains available until the next inflate_add() call. */ - if (((php_zlib_context *) ctx)->status == Z_STREAM_END) + if (ctx->status == Z_STREAM_END) { - ((php_zlib_context *) ctx)->status = Z_OK; - inflateReset(ctx); + ctx->status = Z_OK; + inflateReset(&ctx->Z); } if (in_len <= 0 && flush_type != Z_FINISH) { @@ -947,24 +994,24 @@ PHP_FUNCTION(inflate_add) } out = zend_string_alloc((in_len > CHUNK_SIZE) ? in_len : CHUNK_SIZE, 0); - ctx->next_in = (Bytef *) in_buf; - ctx->next_out = (Bytef *) ZSTR_VAL(out); - ctx->avail_in = in_len; - ctx->avail_out = ZSTR_LEN(out); + ctx->Z.next_in = (Bytef *) in_buf; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out); + ctx->Z.avail_in = in_len; + ctx->Z.avail_out = ZSTR_LEN(out); do { - status = inflate(ctx, flush_type); - buffer_used = ZSTR_LEN(out) - ctx->avail_out; + status = inflate(&ctx->Z, flush_type); + buffer_used = ZSTR_LEN(out) - ctx->Z.avail_out; - ((php_zlib_context *) ctx)->status = status; /* Save status for exposing to userspace */ + ctx->status = status; /* Save status for exposing to userspace */ switch (status) { case Z_OK: - if (ctx->avail_out == 0) { + if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); - ctx->avail_out = CHUNK_SIZE; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = CHUNK_SIZE; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; } else { goto complete; @@ -972,29 +1019,28 @@ PHP_FUNCTION(inflate_add) case Z_STREAM_END: goto complete; case Z_BUF_ERROR: - if (flush_type == Z_FINISH && ctx->avail_out == 0) { + if (flush_type == Z_FINISH && ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); - ctx->avail_out = CHUNK_SIZE; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = CHUNK_SIZE; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; } else { /* No more input data; we're finished */ goto complete; } case Z_NEED_DICT: - if (((php_zlib_context *) ctx)->inflateDict) { - php_zlib_context *php_ctx = (php_zlib_context *) ctx; - switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) { + if (ctx->inflateDict) { + switch (inflateSetDictionary(&ctx->Z, (Bytef *) ctx->inflateDict, ctx->inflateDictlen)) { case Z_OK: - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; + efree(ctx->inflateDict); + ctx->inflateDict = NULL; break; case Z_DATA_ERROR: - php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); - efree(php_ctx->inflateDict); + efree(ctx->inflateDict); + ctx->inflateDict = NULL; zend_string_release_ex(out, 0); - php_ctx->inflateDict = NULL; + php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); RETURN_FALSE; EMPTY_SWITCH_DEFAULT_CASE() } @@ -1010,11 +1056,10 @@ PHP_FUNCTION(inflate_add) } } while (1); - complete: { - out = zend_string_realloc(out, buffer_used, 0); - ZSTR_VAL(out)[buffer_used] = 0; - RETURN_STR(out); - } +complete: + out = zend_string_realloc(out, buffer_used, 0); + ZSTR_VAL(out)[buffer_used] = 0; + RETURN_STR(out); } /* }}} */ @@ -1023,18 +1068,15 @@ PHP_FUNCTION(inflate_add) PHP_FUNCTION(inflate_get_status) { zval *res; - z_stream *ctx; + php_zlib_context *ctx; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res)) - { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &res, inflate_context_ce) != SUCCESS) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); - RETURN_LONG(((php_zlib_context *) ctx)->status); + RETURN_LONG(ctx->status); } /* }}} */ @@ -1043,26 +1085,23 @@ PHP_FUNCTION(inflate_get_status) PHP_FUNCTION(inflate_get_read_len) { zval *res; - z_stream *ctx; + php_zlib_context *ctx; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res)) - { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &res, inflate_context_ce) != SUCCESS) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); - RETURN_LONG(ctx->total_in); + RETURN_LONG(ctx->Z.total_in); } /* }}} */ -/* {{{ proto resource deflate_init(int encoding[, array options]) +/* {{{ proto DeflateContext deflate_init(int encoding[, array options]) Initialize an incremental deflate context using the specified encoding */ PHP_FUNCTION(deflate_init) { - z_stream *ctx; + php_zlib_context *ctx; zend_long encoding, level = -1, memory = 8, window = 15, strategy = Z_DEFAULT_STRATEGY; char *dict = NULL; size_t dictlen = 0; @@ -1077,7 +1116,7 @@ PHP_FUNCTION(deflate_init) level = zval_get_long(option_buffer); } if (level < -1 || level > 9) { - zend_value_error("Compression level (" ZEND_LONG_FMT ") must be within -1..9", level); + zend_value_error("deflate_init(): \"level\" option must be between -1 and 9"); RETURN_THROWS(); } @@ -1085,7 +1124,7 @@ PHP_FUNCTION(deflate_init) memory = zval_get_long(option_buffer); } if (memory < 1 || memory > 9) { - zend_value_error("Compression memory level (" ZEND_LONG_FMT ") must be within 1..9", memory); + zend_value_error("deflate_init(): \"memory\" option must be between 1 and 9"); RETURN_THROWS(); } @@ -1093,7 +1132,7 @@ PHP_FUNCTION(deflate_init) window = zval_get_long(option_buffer); } if (window < 8 || window > 15) { - zend_value_error("zlib window size (logarithm) (" ZEND_LONG_FMT ") must be within 8..15", window); + zend_value_error("deflate_init(): \"window\" option must be between 8 and 15"); RETURN_THROWS(); } @@ -1108,12 +1147,12 @@ PHP_FUNCTION(deflate_init) case Z_DEFAULT_STRATEGY: break; default: - zend_value_error("Strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY"); + zend_value_error("deflate_init(): \"strategy\" option must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY"); RETURN_THROWS(); } if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_FALSE; + RETURN_THROWS(); } switch (encoding) { @@ -1122,13 +1161,15 @@ PHP_FUNCTION(deflate_init) case PHP_ZLIB_ENCODING_DEFLATE: break; default: - zend_value_error("Encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); + zend_argument_value_error(1, "must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP, or ZLIB_ENCODING_DEFLATE"); RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(php_zlib_context)); - ctx->zalloc = php_zlib_alloc; - ctx->zfree = php_zlib_free; + object_init_ex(return_value, deflate_context_ce); + ctx = Z_DEFLATE_CONTEXT_P(return_value); + + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; if (encoding < 0) { encoding += 15 - window; @@ -1136,23 +1177,21 @@ PHP_FUNCTION(deflate_init) encoding -= 15 - window; } - if (Z_OK == deflateInit2(ctx, level, Z_DEFLATED, encoding, memory, strategy)) { - if (dict) { - int success = deflateSetDictionary(ctx, (Bytef *) dict, dictlen); - ZEND_ASSERT(success == Z_OK); - efree(dict); - } - - RETURN_RES(zend_register_resource(ctx, le_deflate)); - } else { - efree(ctx); + if (deflateInit2(&ctx->Z, level, Z_DEFLATED, encoding, memory, strategy) != Z_OK) { + zval_ptr_dtor(return_value); php_error_docref(NULL, E_WARNING, "Failed allocating zlib.deflate context"); RETURN_FALSE; } + + if (dict) { + int success = deflateSetDictionary(&ctx->Z, (Bytef *) dict, dictlen); + ZEND_ASSERT(success == Z_OK); + efree(dict); + } } /* }}} */ -/* {{{ proto string deflate_add(resource context, string data[, int flush_mode = ZLIB_SYNC_FLUSH]) +/* {{{ proto string deflate_add(DeflateContext context, string data[, int flush_mode = ZLIB_SYNC_FLUSH]) Incrementally deflate data in the specified context */ PHP_FUNCTION(deflate_add) { @@ -1160,17 +1199,15 @@ PHP_FUNCTION(deflate_add) char *in_buf; size_t in_len, out_size, buffer_used; zval *res; - z_stream *ctx; + php_zlib_context *ctx; zend_long flush_type = Z_SYNC_FLUSH; int status; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &res, deflate_context_ce, &in_buf, &in_len, &flush_type)) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_deflate_name, le_deflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_DEFLATE_CONTEXT_P(res); switch (flush_type) { case Z_BLOCK: @@ -1186,8 +1223,7 @@ PHP_FUNCTION(deflate_add) break; default: - zend_value_error( - "Flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH"); + zend_argument_value_error(3, "must be one of ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK, or ZLIB_FINISH"); RETURN_THROWS(); } @@ -1199,35 +1235,35 @@ PHP_FUNCTION(deflate_add) out_size = (out_size < 64) ? 64 : out_size; out = zend_string_alloc(out_size, 0); - ctx->next_in = (Bytef *) in_buf; - ctx->next_out = (Bytef *) ZSTR_VAL(out); - ctx->avail_in = in_len; - ctx->avail_out = ZSTR_LEN(out); + ctx->Z.next_in = (Bytef *) in_buf; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out); + ctx->Z.avail_in = in_len; + ctx->Z.avail_out = ZSTR_LEN(out); buffer_used = 0; do { - if (ctx->avail_out == 0) { + if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ /* adding 64 more bytes solved every issue I have seen */ out = zend_string_realloc(out, ZSTR_LEN(out) + 64, 0); - ctx->avail_out = 64; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = 64; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; } - status = deflate(ctx, flush_type); - buffer_used = ZSTR_LEN(out) - ctx->avail_out; - } while (status == Z_OK && ctx->avail_out == 0); + status = deflate(&ctx->Z, flush_type); + buffer_used = ZSTR_LEN(out) - ctx->Z.avail_out; + } while (status == Z_OK && ctx->Z.avail_out == 0); switch (status) { case Z_OK: - ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out); + ZSTR_LEN(out) = (char *) ctx->Z.next_out - ZSTR_VAL(out); ZSTR_VAL(out)[ZSTR_LEN(out)] = 0; RETURN_STR(out); break; case Z_STREAM_END: - ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out); + ZSTR_LEN(out) = (char *) ctx->Z.next_out - ZSTR_VAL(out); ZSTR_VAL(out)[ZSTR_LEN(out)] = 0; - deflateReset(ctx); + deflateReset(&ctx->Z); RETURN_STR(out); break; default: @@ -1320,8 +1356,33 @@ static PHP_MINIT_FUNCTION(zlib) php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check); php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check); - le_deflate = zend_register_list_destructors_ex(deflate_rsrc_dtor, NULL, "zlib.deflate", module_number); - le_inflate = zend_register_list_destructors_ex(inflate_rsrc_dtor, NULL, "zlib.inflate", module_number); + zend_class_entry inflate_ce; + INIT_CLASS_ENTRY(inflate_ce, "InflateContext", class_InflateContext_methods); + inflate_context_ce = zend_register_internal_class(&inflate_ce); + inflate_context_ce->ce_flags |= ZEND_ACC_FINAL; + inflate_context_ce->create_object = inflate_context_create_object; + inflate_context_ce->serialize = zend_class_serialize_deny; + inflate_context_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&inflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + inflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + inflate_context_object_handlers.free_obj = inflate_context_free_obj; + inflate_context_object_handlers.get_constructor = inflate_context_get_constructor; + inflate_context_object_handlers.clone_obj = NULL; + + zend_class_entry deflate_ce; + INIT_CLASS_ENTRY(deflate_ce, "DeflateContext", class_DeflateContext_methods); + deflate_context_ce = zend_register_internal_class(&deflate_ce); + deflate_context_ce->ce_flags |= ZEND_ACC_FINAL; + deflate_context_ce->create_object = deflate_context_create_object; + deflate_context_ce->serialize = zend_class_serialize_deny; + deflate_context_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&deflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + deflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + deflate_context_object_handlers.free_obj = deflate_context_free_obj; + deflate_context_object_handlers.get_constructor = deflate_context_get_constructor; + deflate_context_object_handlers.clone_obj = NULL; REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT); diff --git a/ext/zlib/zlib.stub.php b/ext/zlib/zlib.stub.php index c3f87e5ccc35e..8f4ba12c7964c 100644 --- a/ext/zlib/zlib.stub.php +++ b/ext/zlib/zlib.stub.php @@ -2,6 +2,14 @@ /** @generate-function-entries */ +final class InflateContext +{ +} + +final class DeflateContext +{ +} + function ob_gzhandler(string $data, int $flags): string|false {} function zlib_get_coding_type(): string|false {} @@ -95,20 +103,14 @@ function gzread($fp, int $length): string|false {} */ function gzgets($fp, int $length = 1024): string|false {} -/** @return resource|false */ -function deflate_init(int $encoding, array $options = []) {} +function deflate_init(int $encoding, array $options = []): DeflateContext|false {} -/** @param resource $resource */ -function deflate_add($resource, string $add, int $flush_behavior = ZLIB_SYNC_FLUSH): string|false {} +function deflate_add(DeflateContext $context, string $add, int $flush_behavior = ZLIB_SYNC_FLUSH): string|false {} -/** @return resource|false */ -function inflate_init(int $encoding, array $options = []) {} +function inflate_init(int $encoding, array $options = []): InflateContext|false {} -/** @param resource $context */ -function inflate_add($context, string $encoded_data, int $flush_mode = ZLIB_SYNC_FLUSH): string|false {} +function inflate_add(InflateContext $context, string $encoded_data, int $flush_mode = ZLIB_SYNC_FLUSH): string|false {} -/** @param resource $resource */ -function inflate_get_status($resource): int {} +function inflate_get_status(InflateContext $context): int {} -/** @param resource $resource */ -function inflate_get_read_len($resource): int {} +function inflate_get_read_len(InflateContext $context): int {} diff --git a/ext/zlib/zlib_arginfo.h b/ext/zlib/zlib_arginfo.h index b86926c906207..2a5112391ed87 100644 --- a/ext/zlib/zlib_arginfo.h +++ b/ext/zlib/zlib_arginfo.h @@ -103,27 +103,30 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_gzgets, 0, 1, MAY_BE_STRING|MAY_ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "1024") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_deflate_init, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_deflate_init, 0, 1, DeflateContext, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, encoding, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_deflate_add, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, resource) + ZEND_ARG_OBJ_INFO(0, context, DeflateContext, 0) ZEND_ARG_TYPE_INFO(0, add, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flush_behavior, IS_LONG, 0, "ZLIB_SYNC_FLUSH") ZEND_END_ARG_INFO() -#define arginfo_inflate_init arginfo_deflate_init +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_inflate_init, 0, 1, InflateContext, MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, encoding, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_inflate_add, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, context) + ZEND_ARG_OBJ_INFO(0, context, InflateContext, 0) ZEND_ARG_TYPE_INFO(0, encoded_data, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flush_mode, IS_LONG, 0, "ZLIB_SYNC_FLUSH") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_inflate_get_status, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, resource) + ZEND_ARG_OBJ_INFO(0, context, InflateContext, 0) ZEND_END_ARG_INFO() #define arginfo_inflate_get_read_len arginfo_inflate_get_status @@ -193,3 +196,13 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(inflate_get_read_len, arginfo_inflate_get_read_len) ZEND_FE_END }; + + +static const zend_function_entry class_InflateContext_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_DeflateContext_methods[] = { + ZEND_FE_END +};