From 3cafa7f4df07e2dd5c4f34e74bfdf2631fc2ef6a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 15 Feb 2019 11:20:28 +0100 Subject: [PATCH] Assign (un)serialize_func during compilation This avoids writing this cache at runtime, which is illegal if preloading is used. Not every serialize/unserialize function actually belongs to the Serializable interface, but I think it's not a problem to assign these anyway -- whether they are used ultimately depends on whether Serializable is implemented. Alternatively it might make sense to just drop these entirely. I don't think this is performance critical functionality. --- Zend/zend_API.c | 8 +++++++- Zend/zend_compile.c | 4 ++++ Zend/zend_inheritance.c | 12 +++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index f191ca25b9..97ccb61141 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2093,7 +2093,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; + 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_string *lowercase_name; size_t fname_len; const char *lc_class_name = NULL; @@ -2268,6 +2268,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio */ if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) { ctor = reg_function; + } else 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] != '_') { reg_function = NULL; } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) { @@ -2339,6 +2343,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; if (ctor) { ctor->common.fn_flags |= ZEND_ACC_CTOR; if (ctor->common.fn_flags & ZEND_ACC_STATIC) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 03f8cf2563..f814c48b3b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5637,6 +5637,10 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo if (!ce->constructor) { ce->constructor = (zend_function *) op_array; } + } else 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 (!is_static) { op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 858a36213c..2ce4df3049 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -124,9 +124,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_func)) { + ce->unserialize_func = parent->unserialize_func; + } if (EXPECTED(!ce->unserialize)) { ce->unserialize = parent->unserialize; } @@ -1287,7 +1293,11 @@ static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */ { - if (ZSTR_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) { + 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_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) { /* pass */ } else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) { ce->clone = fe; -- 2.50.0