]> granicus.if.org Git - php/commitdiff
Cache __unserialize() instead of unserialize()
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 26 Jun 2020 08:54:40 +0000 (10:54 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 26 Jun 2020 08:54:40 +0000 (10:54 +0200)
We should use these cache slots for the new object serialization
mechanism rather than the old one.

Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_compile.c
Zend/zend_inheritance.c
Zend/zend_interfaces.c
ext/opcache/zend_accelerator_util_funcs.c
ext/opcache/zend_file_cache.c
ext/opcache/zend_persist.c
ext/standard/var.c
ext/standard/var_unserializer.re

index 997f2e705368b79c74fea0e36338f01303ec6289..4fe89fcacc809936a20e9ae1224e32cf730192c3 100644 (file)
@@ -140,8 +140,8 @@ struct _zend_class_entry {
        zend_function *__callstatic;
        zend_function *__tostring;
        zend_function *__debugInfo;
-       zend_function *serialize_func;
-       zend_function *unserialize_func;
+       zend_function *__serialize;
+       zend_function *__unserialize;
 
        /* allocated only if class implements Iterator or IteratorAggregate interface */
        zend_class_iterator_funcs *iterator_funcs_ptr;
index 1d18b047d343302114b36a690bb4109f6de726fb..14075847ad1f5c088399feb71593c95cf0ac0fc9 100644 (file)
@@ -2056,7 +2056,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
        int count=0, unload=0;
        HashTable *target_function_table = function_table;
        int error_type;
-       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL, *serialize_func = NULL, *unserialize_func = NULL;
+       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL, *__serialize = NULL, *__unserialize = NULL;
        zend_string *lowercase_name;
        size_t fname_len;
        const char *lc_class_name = NULL;
@@ -2222,11 +2222,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
 
                if (scope) {
                        /* Look for ctor, dtor, clone */
-                       if (zend_string_equals_literal(lowercase_name, "serialize")) {
-                               serialize_func = reg_function;
-                       } else if (zend_string_equals_literal(lowercase_name, "unserialize")) {
-                               unserialize_func = reg_function;
-                       } else if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') {
+                       if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') {
                                reg_function = NULL;
                        } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
                                ctor = reg_function;
@@ -2257,6 +2253,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                                scope->ce_flags |= ZEND_ACC_USE_GUARDS;
                        } else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
                                __debugInfo = reg_function;
+                       } else if (zend_string_equals_literal(lowercase_name, "__serialize")) {
+                               __serialize = reg_function;
+                       } else if (zend_string_equals_literal(lowercase_name, "__unserialize")) {
+                               __unserialize = reg_function;
                        } else {
                                reg_function = NULL;
                        }
@@ -2298,8 +2298,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                scope->__unset = __unset;
                scope->__isset = __isset;
                scope->__debugInfo = __debugInfo;
-               scope->serialize_func = serialize_func;
-               scope->unserialize_func = unserialize_func;
+               scope->__serialize = __serialize;
+               scope->__unserialize = __unserialize;
                if (ctor) {
                        ctor->common.fn_flags |= ZEND_ACC_CTOR;
                        if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
index bdcdfaea318f4898424c1dc995b46f6d7064c1c2..9744612ac7460168e5c990d417be982e0e66a760 100644 (file)
@@ -250,8 +250,8 @@ typedef struct _zend_fcall_info_cache {
                class_container.__unset = NULL;                                                 \
                class_container.__isset = NULL;                                                 \
                class_container.__debugInfo = NULL;                                             \
-               class_container.serialize_func = NULL;                                  \
-               class_container.unserialize_func = NULL;                                \
+               class_container.__serialize = NULL;                                             \
+               class_container.__unserialize = NULL;                                   \
                class_container.parent = NULL;                                                  \
                class_container.num_interfaces = 0;                                             \
                class_container.trait_names = NULL;                                             \
index f65e4a94ec8ef7d78413fbd2ced572881b2b2065..de5b8581e8aee0ca976e705b4cad23d0abb0d6a7 100644 (file)
@@ -1835,6 +1835,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                ce->__call = NULL;
                ce->__callstatic = NULL;
                ce->__tostring = NULL;
+               ce->__serialize = NULL;
+               ce->__unserialize = NULL;
+               ce->__debugInfo = NULL;
                ce->create_object = NULL;
                ce->get_iterator = NULL;
                ce->iterator_funcs_ptr = NULL;
@@ -1849,9 +1852,6 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                ce->trait_precedences = NULL;
                ce->serialize = NULL;
                ce->unserialize = NULL;
-               ce->serialize_func = NULL;
-               ce->unserialize_func = NULL;
-               ce->__debugInfo = NULL;
                if (ce->type == ZEND_INTERNAL_CLASS) {
                        ce->info.internal.module = NULL;
                        ce->info.internal.builtin_functions = NULL;
@@ -6256,11 +6256,7 @@ zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name,
                        ZSTR_VAL(ce->name), ZSTR_VAL(name));
        }
 
-       if (zend_string_equals_literal(lcname, "serialize")) {
-               ce->serialize_func = (zend_function *) op_array;
-       } else if (zend_string_equals_literal(lcname, "unserialize")) {
-               ce->unserialize_func = (zend_function *) op_array;
-       } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
+       if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
                /* pass */
        } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
                ce->constructor = (zend_function *) op_array;
@@ -6301,8 +6297,10 @@ zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name,
                ce->__debugInfo = (zend_function *) op_array;
        } else if (zend_string_equals_literal(lcname, "__serialize")) {
                zend_check_magic_method_attr(fn_flags, ce, "__serialize", 0);
+               ce->__serialize = (zend_function *) op_array;
        } else if (zend_string_equals_literal(lcname, "__unserialize")) {
                zend_check_magic_method_attr(fn_flags, ce, "__unserialize", 0);
+               ce->__unserialize = (zend_function *) op_array;
        } else if (zend_string_equals_literal(lcname, "__set_state")) {
         zend_check_magic_method_attr(fn_flags, ce, "__set_state", 1);
        }
index 7cee42085bf584bdf683be1b70a4680f76b0e135..8a3c9ba1aac45e220cdf14ef2d22d2723b4a63f6 100644 (file)
@@ -167,15 +167,15 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
        if (EXPECTED(!ce->clone)) {
                ce->clone = parent->clone;
        }
-       if (EXPECTED(!ce->serialize_func)) {
-               ce->serialize_func = parent->serialize_func;
+       if (EXPECTED(!ce->__serialize)) {
+               ce->__serialize = parent->__serialize;
+       }
+       if (EXPECTED(!ce->__unserialize)) {
+               ce->__unserialize = parent->__unserialize;
        }
        if (EXPECTED(!ce->serialize)) {
                ce->serialize = parent->serialize;
        }
-       if (EXPECTED(!ce->unserialize_func)) {
-               ce->unserialize_func = parent->unserialize_func;
-       }
        if (EXPECTED(!ce->unserialize)) {
                ce->unserialize = parent->unserialize;
        }
@@ -1557,11 +1557,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry
 
 static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */
 {
-       if (zend_string_equals_literal(mname, "serialize")) {
-               ce->serialize_func = fe;
-       } else if (zend_string_equals_literal(mname, "unserialize")) {
-               ce->unserialize_func = fe;
-       } else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') {
+       if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') {
                /* pass */
        } else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
                ce->clone = fe;
@@ -1589,6 +1585,10 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
                ce->__tostring = fe;
        } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
                ce->__debugInfo = fe;
+       } else if (zend_string_equals_literal(mname, "__serialize")) {
+               ce->__serialize = fe;
+       } else if (zend_string_equals_literal(mname, "__unserialize")) {
+               ce->__unserialize = fe;
        }
 }
 /* }}} */
index 3009af2b3f103bc8b82443996350842f60d0d4d4..a100176c367addc5dd011b47fc87b7a975c2df88 100644 (file)
@@ -357,7 +357,8 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *b
        zval retval;
        int result;
 
-       zend_call_known_instance_method_with_0_params(ce->serialize_func, Z_OBJ_P(object), &retval);
+       zend_call_method_with_0_params(
+               Z_OBJ_P(object), Z_OBJCE_P(object), NULL, "serialize", &retval);
 
        if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) {
                result = FAILURE;
@@ -396,8 +397,8 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns
        }
 
        ZVAL_STRINGL(&zdata, (char*)buf, buf_len);
-       zend_call_known_instance_method_with_1_params(
-               ce->unserialize_func, Z_OBJ_P(object), NULL, &zdata);
+       zend_call_method_with_1_params(
+               Z_OBJ_P(object), Z_OBJCE_P(object), NULL, "unserialize", NULL, &zdata);
        zval_ptr_dtor(&zdata);
 
        if (EG(exception)) {
index db2ee8c434856875dbb7183c1afc3b71dc34045a..cfd70eec120a837558a528d06c41939156d82f09 100644 (file)
@@ -369,17 +369,13 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
        zend_update_inherited_handler(__get);
        zend_update_inherited_handler(__set);
        zend_update_inherited_handler(__call);
-/* 5.1 stuff */
-       zend_update_inherited_handler(serialize_func);
-       zend_update_inherited_handler(unserialize_func);
        zend_update_inherited_handler(__isset);
        zend_update_inherited_handler(__unset);
-/* 5.2 stuff */
        zend_update_inherited_handler(__tostring);
-
-/* 5.3 stuff */
        zend_update_inherited_handler(__callstatic);
        zend_update_inherited_handler(__debugInfo);
+       zend_update_inherited_handler(__serialize);
+       zend_update_inherited_handler(__unserialize);
 
 /* 5.4 traits */
        if (ce->num_traits) {
index 7bf36b7931e5a33b7576a12f95b7ecfbb7fb21bf..15ade4ce3c07995735722ab4a5d0617a5e9677dd 100644 (file)
@@ -827,8 +827,8 @@ static void zend_file_cache_serialize_class(zval                     *zv,
        SERIALIZE_PTR(ce->__get);
        SERIALIZE_PTR(ce->__set);
        SERIALIZE_PTR(ce->__call);
-       SERIALIZE_PTR(ce->serialize_func);
-       SERIALIZE_PTR(ce->unserialize_func);
+       SERIALIZE_PTR(ce->__serialize);
+       SERIALIZE_PTR(ce->__unserialize);
        SERIALIZE_PTR(ce->__isset);
        SERIALIZE_PTR(ce->__unset);
        SERIALIZE_PTR(ce->__tostring);
@@ -1564,8 +1564,8 @@ static void zend_file_cache_unserialize_class(zval                    *zv,
        UNSERIALIZE_PTR(ce->__get);
        UNSERIALIZE_PTR(ce->__set);
        UNSERIALIZE_PTR(ce->__call);
-       UNSERIALIZE_PTR(ce->serialize_func);
-       UNSERIALIZE_PTR(ce->unserialize_func);
+       UNSERIALIZE_PTR(ce->__serialize);
+       UNSERIALIZE_PTR(ce->__unserialize);
        UNSERIALIZE_PTR(ce->__isset);
        UNSERIALIZE_PTR(ce->__unset);
        UNSERIALIZE_PTR(ce->__tostring);
index 1ad195c6899fe1ce284b1d164ee33e0984cd0632..ae997b9a609076d3c858d247705005f7339b0de2 100644 (file)
@@ -1090,16 +1090,16 @@ static void zend_update_parent_ce(zend_class_entry *ce)
                        ce->__call = tmp;
                }
        }
-       if (ce->serialize_func) {
-               zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
+       if (ce->__serialize) {
+               zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__serialize);
                if (tmp != NULL) {
-                       ce->serialize_func = tmp;
+                       ce->__serialize = tmp;
                }
        }
-       if (ce->unserialize_func) {
-               zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
+       if (ce->__unserialize) {
+               zend_function *tmp = zend_shared_alloc_get_xlat_entry(ce->__unserialize);
                if (tmp != NULL) {
-                       ce->unserialize_func = tmp;
+                       ce->__unserialize = tmp;
                }
        }
        if (ce->__isset) {
index 4d47e67e2c7d15b73d492feedad581da6d019bef..d96f3735433eec08f99c9fa04e9538f308669589 100644 (file)
@@ -743,16 +743,12 @@ static int php_var_serialize_call_sleep(zval *retval, zval *struc) /* {{{ */
 
 static int php_var_serialize_call_magic_serialize(zval *retval, zval *obj) /* {{{ */
 {
-       zval fname;
-       int res;
-
-       ZVAL_STRINGL(&fname, "__serialize", sizeof("__serialize") - 1);
        BG(serialize_lock)++;
-       res = call_user_function(CG(function_table), obj, &fname, retval, 0, 0);
+       zend_call_known_instance_method_with_0_params(
+               Z_OBJCE_P(obj)->__serialize, Z_OBJ_P(obj), retval);
        BG(serialize_lock)--;
-       zval_ptr_dtor_str(&fname);
 
-       if (res == FAILURE || Z_ISUNDEF_P(retval)) {
+       if (EG(exception)) {
                zval_ptr_dtor(retval);
                return FAILURE;
        }
@@ -995,7 +991,7 @@ again:
                                zend_bool incomplete_class;
                                uint32_t count;
 
-                               if (zend_hash_str_exists(&ce->function_table, "__serialize", sizeof("__serialize")-1)) {
+                               if (ce->__serialize) {
                                        zval retval, obj;
                                        zend_string *key;
                                        zval *data;
index 8766b3f2f1495133ea31ac1617f6e23dd35269d1..9aadaf58431c745ac86e5b43debc43a40dff7873 100644 (file)
@@ -218,9 +218,8 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
        var_entries *var_hash = (*var_hashx)->entries.next;
        var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
        zend_bool delayed_call_failed = 0;
-       zval wakeup_name, unserialize_name;
+       zval wakeup_name;
        ZVAL_UNDEF(&wakeup_name);
-       ZVAL_UNDEF(&unserialize_name);
 
 #if VAR_ENTRIES_DBG
        fprintf(stderr, "var_destroy( " ZEND_LONG_FMT ")\n", var_hash?var_hash->used_slots:-1L);
@@ -261,22 +260,18 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
                        } else if (Z_EXTRA_P(zv) == VAR_UNSERIALIZE_FLAG) {
                                /* Perform delayed __unserialize calls */
                                if (!delayed_call_failed) {
-                                       zval retval, param;
+                                       zval param;
                                        ZVAL_COPY(&param, &var_dtor_hash->data[i + 1]);
 
-                                       if (Z_ISUNDEF(unserialize_name)) {
-                                               ZVAL_STRINGL(&unserialize_name, "__unserialize", sizeof("__unserialize") - 1);
-                                       }
-
                                        BG(serialize_lock)++;
-                                       if (call_user_function(CG(function_table), zv, &unserialize_name, &retval, 1, &param) == FAILURE || Z_ISUNDEF(retval)) {
+                                       zend_call_known_instance_method_with_1_params(
+                                               Z_OBJCE_P(zv)->__unserialize, Z_OBJ_P(zv), NULL, &param);
+                                       if (EG(exception)) {
                                                delayed_call_failed = 1;
                                                GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
                                        }
                                        BG(serialize_lock)--;
-
                                        zval_ptr_dtor(&param);
-                                       zval_ptr_dtor(&retval);
                                } else {
                                        GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
                                }
@@ -290,7 +285,6 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
        }
 
        zval_ptr_dtor_nogc(&wakeup_name);
-       zval_ptr_dtor_nogc(&unserialize_name);
 
        if ((*var_hashx)->ref_props) {
                zend_hash_destroy((*var_hashx)->ref_props);
@@ -1169,8 +1163,7 @@ object ":" uiv ":" ["]    {
 
        *p += 2;
 
-       has_unserialize = !incomplete_class
-               && zend_hash_str_exists(&ce->function_table, "__unserialize", sizeof("__unserialize")-1);
+       has_unserialize = !incomplete_class && ce->__unserialize;
 
        /* If this class implements Serializable, it should not land here but in object_custom().
         * The passed string obviously doesn't descend from the regular serializer. However, if