From 0c6fc20f8b55ef84a927a2cd2d49cd4141c9ae08 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 5 Mar 2021 09:16:22 +0100 Subject: patches --- uopz-php8.patch | 490 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ uopz-xdebug.patch | 72 -------- 2 files changed, 490 insertions(+), 72 deletions(-) create mode 100644 uopz-php8.patch delete mode 100644 uopz-xdebug.patch diff --git a/uopz-php8.patch b/uopz-php8.patch new file mode 100644 index 0000000..200fd2d --- /dev/null +++ b/uopz-php8.patch @@ -0,0 +1,490 @@ +From ce0b480bd6446c81b909451cebd54fb8c53c8590 Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" +Date: Fri, 21 Aug 2020 10:13:33 +0200 +Subject: [PATCH 3/7] Skip unsupported tests on PHP 7.4+ with OPcache + +As of PHP 7.4.0, uopz can no longer support manipulation of immutable +classes and functions when OPcache is enabled. Therefore, we skip the +respective test cases under these conditions. + +We also have to make sure that the `die()`s are actually executed. +--- + tests/016.phpt | 12 +++++++++++- + tests/bugs/gh76.phpt | 8 ++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/tests/016.phpt b/tests/016.phpt +index 3d65ea4..79e9b3a 100644 +--- a/tests/016.phpt ++++ b/tests/016.phpt +@@ -1,7 +1,17 @@ + --TEST-- + uopz_flags + --SKIPIF-- +- ++=') ++ && function_exists('opcache_get_status') ++ && ($status = opcache_get_status()) ++ && $status['opcache_enabled']) ++{ ++ die('skip not for PHP 7.4+ with OPcache'); ++} ++?> + --INI-- + uopz.disable=0 + --FILE-- +diff --git a/tests/bugs/gh76.phpt b/tests/bugs/gh76.phpt +index 62680c3..ef09976 100644 +--- a/tests/bugs/gh76.phpt ++++ b/tests/bugs/gh76.phpt +@@ -3,6 +3,14 @@ uopz_extend affects only explicit calls via parent:: but not inherited methods + --SKIPIF-- + =') ++ && function_exists('opcache_get_status') ++ && ($status = opcache_get_status()) ++ && $status['opcache_enabled']) ++{ ++ die('skip not for PHP 7.4+ with OPcache'); ++} + ?> + --INI-- + uopz.disable=0 +-- +2.29.2 + +From 0f975b64248ecc0af579370e1266b0cfc5775c69 Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" +Date: Thu, 20 Aug 2020 16:23:34 +0200 +Subject: [PATCH 4/7] Don't remove methods of immutable classes + +These are not fully reloaded by OPcache, so the methods would be +missing after the first request shutdown. + +Cf. . +--- + src/util.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/util.c b/src/util.c +index 707b236..fce1fd3 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -169,7 +169,12 @@ int uopz_clean_function(zval *zv) { /* {{{ */ + + int uopz_clean_class(zval *zv) { /* {{{ */ + zend_class_entry *ce = Z_PTR_P(zv); +- ++ ++#if PHP_VERSION_ID >= 70400 ++ if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { ++ return ZEND_HASH_APPLY_KEEP; ++ } ++#endif + zend_hash_apply( + &ce->function_table, uopz_clean_function); + +-- +2.29.2 + +From cfaa8987096117eb0c921ef0c927320b4831b725 Mon Sep 17 00:00:00 2001 +From: Joe Watkins +Date: Thu, 1 Oct 2020 10:12:07 +0200 +Subject: [PATCH 5/7] php 8 support + +--- + src/class.c | 14 ++++++++++++++ + src/copy.c | 9 ++++++++- + src/function.c | 8 ++++++-- + src/handlers.c | 20 +++++++++++++++++--- + src/hook.c | 4 ++++ + src/return.c | 4 ++++ + src/util.c | 12 +++++++++++- + tests/012.phpt | 2 +- + tests/018.phpt | 4 ++-- + tests/035.phpt | 2 +- + tests/040.phpt | 2 +- + tests/bugs/gh102.phpt | 2 +- + uopz.c | 16 ++++++++++++++-- + 13 files changed, 84 insertions(+), 15 deletions(-) + +diff --git a/src/class.c b/src/class.c +index 95fa0f2..555577e 100644 +--- a/src/class.c ++++ b/src/class.c +@@ -220,6 +220,10 @@ zend_bool uopz_implement(zend_class_entry *clazz, zend_class_entry *interface) { + + zend_do_implement_interface(clazz, interface); + ++#if PHP_VERSION_ID >= 80000 ++ clazz->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES; ++#endif ++ + return instanceof_function(clazz, interface); + } /* }}} */ + +@@ -246,8 +250,13 @@ void uopz_set_property(zval *object, zval *member, zval *value) { /* {{{ */ + uopz_set_scope(Z_OBJCE_P(object)); + } + ++#if PHP_VERSION_ID >= 80000 ++ Z_OBJ_HT_P(object) ++ ->write_property(Z_OBJ_P(object), Z_STR_P(member), value, NULL); ++#else + Z_OBJ_HT_P(object) + ->write_property(object, member, value, NULL); ++#endif + + uopz_set_scope(scope); + } /* }}} */ +@@ -276,8 +285,13 @@ void uopz_get_property(zval *object, zval *member, zval *value) { /* {{{ */ + uopz_set_scope(Z_OBJCE_P(object)); + } + ++#if PHP_VERSION_ID >= 80000 ++ prop = Z_OBJ_HT_P(object)->read_property( ++ Z_OBJ_P(object), Z_STR_P(member), BP_VAR_R, NULL, &rv); ++#else + prop = Z_OBJ_HT_P(object)->read_property( + object, member, BP_VAR_R, NULL, &rv); ++#endif + + uopz_set_scope(scope); + +diff --git a/src/copy.c b/src/copy.c +index 11b1414..c8ddb0e 100644 +--- a/src/copy.c ++++ b/src/copy.c +@@ -176,7 +176,14 @@ static inline zend_arg_info* uopz_copy_arginfo(zend_op_array *op_array, zend_arg + while (it < end) { + if (info[it].name) + info[it].name = zend_string_copy(old[it].name); +-#if PHP_VERSION_ID >= 70200 ++#if PHP_VERSION_ID >= 80000 ++ if (ZEND_TYPE_IS_SET(old[it].type) && ZEND_TYPE_HAS_CLASS(old[it].type)) { ++ info[it].type = (zend_type) ZEND_TYPE_INIT_CLASS( ++ zend_string_copy( ++ ZEND_TYPE_NAME(info[it].type)), ++ ZEND_TYPE_ALLOW_NULL(info[it].type), 0); ++ } ++#elif PHP_VERSION_ID >= 70200 + if (ZEND_TYPE_IS_SET(old[it].type) && ZEND_TYPE_IS_CLASS(old[it].type)) { + info[it].type = ZEND_TYPE_ENCODE_CLASS( + zend_string_copy( +diff --git a/src/function.c b/src/function.c +index 8ce6c72..4245bd2 100644 +--- a/src/function.c ++++ b/src/function.c +@@ -60,11 +60,15 @@ zend_bool uopz_add_function(zend_class_entry *clazz, zend_string *name, zval *cl + + zend_hash_update(functions, key, closure); + zval_copy_ctor(closure); +- ++#if PHP_VERSION_ID >= 80000 ++ function = uopz_copy_closure(clazz, ++ (zend_function*) zend_get_closure_method_def(Z_OBJ_P(closure)), ++ flags); ++#else + function = uopz_copy_closure(clazz, + (zend_function*) zend_get_closure_method_def(closure), + flags); +- ++#endif + zend_hash_update_ptr(table, key, (void*) function); + + if (clazz) { +diff --git a/src/handlers.c b/src/handlers.c +index aadf504..a71cc53 100644 +--- a/src/handlers.c ++++ b/src/handlers.c +@@ -143,8 +143,14 @@ UOPZ_HANDLERS_DECL_BEGIN() + UOPZ_HANDLER_DECL(ZEND_INIT_STATIC_METHOD_CALL, init_static_method_call) + UOPZ_HANDLERS_DECL_END() + ++#if PHP_VERSION_ID >= 80000 ++static zend_always_inline zval* uopz_get_zval(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data) { ++#else + static zend_always_inline zval* uopz_get_zval(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type) { +-#if PHP_VERSION_ID >= 70300 ++#endif ++#if PHP_VERSION_ID >= 80000 ++ return zend_get_zval_ptr(opline, op_type, node, execute_data); ++#elif PHP_VERSION_ID >= 70300 + return zend_get_zval_ptr(opline, op_type, node, execute_data, should_free, type); + #else + return zend_get_zval_ptr(op_type, node, execute_data, should_free, type); +@@ -234,7 +240,9 @@ static zend_always_inline int _uopz_vm_dispatch(UOPZ_OPCODE_HANDLER_ARGS) { + int uopz_vm_exit(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ + UOPZ_USE_OPLINE; + zval *estatus; ++#if PHP_VERSION_ID < 80000 + zend_free_op free_op1; ++#endif + + if (UOPZ(exit)) { + UOPZ_VM_DISPATCH(); +@@ -245,8 +253,12 @@ int uopz_vm_exit(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ + opline, + opline->op1_type, + &opline->op1, +- execute_data, +- &free_op1, BP_VAR_R); ++ execute_data ++#if PHP_VERSION_ID < 80000 ++ , &free_op1, BP_VAR_R); ++#else ++ ); ++#endif + + do { + if (Z_TYPE_P(estatus) == IS_LONG) { +@@ -263,9 +275,11 @@ int uopz_vm_exit(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ + } + } while (0); + ++#if PHP_VERSION_ID < 80000 + if (free_op1) { + zval_ptr_dtor_nogc(free_op1); + } ++#endif + + ZVAL_COPY(&UOPZ(estatus), estatus); + } +diff --git a/src/hook.c b/src/hook.c +index 7319ac7..6c03c02 100644 +--- a/src/hook.c ++++ b/src/hook.c +@@ -162,7 +162,11 @@ void uopz_execute_hook(uopz_hook_t *uhook, zend_execute_data *execute_data, zend + + uhook->busy = 1; + ++#if PHP_VERSION_ID >= 80000 ++ zend_create_closure(&closure, (zend_function*) zend_get_closure_method_def(Z_OBJ(uhook->closure)), ++#else + zend_create_closure(&closure, (zend_function*) zend_get_closure_method_def(&uhook->closure), ++#endif + uhook->clazz, uhook->clazz, Z_OBJ(EX(This)) ? &EX(This) : NULL); + + zend_fcall_info_init(&closure, 0, &fci, &fcc, NULL, &error); +diff --git a/src/return.c b/src/return.c +index f47948b..3b6b0c0 100644 +--- a/src/return.c ++++ b/src/return.c +@@ -172,7 +172,11 @@ void uopz_execute_return(uopz_return_t *ureturn, zend_execute_data *execute_data + + ureturn->flags ^= UOPZ_RETURN_BUSY; + ++#if PHP_VERSION_ID >= 80000 ++ zend_create_closure(&closure, (zend_function*) zend_get_closure_method_def(Z_OBJ(ureturn->value)), ++#else + zend_create_closure(&closure, (zend_function*) zend_get_closure_method_def(&ureturn->value), ++#endif + ureturn->clazz, ureturn->clazz, Z_OBJ(EX(This)) ? &EX(This) : NULL); + + zend_fcall_info_init(&closure, 0, &fci, &fcc, NULL, &error); +diff --git a/src/util.c b/src/util.c +index 707b236..311e1cb 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -90,8 +90,13 @@ void uopz_handle_magic(zend_class_entry *clazz, zend_string *name, zend_function + case 7: clazz->__call = function; break; + case 8: clazz->__callstatic = function; break; + case 9: clazz->__tostring = function; break; ++#if PHP_VERSION_ID >= 80000 ++ case 10: clazz->__serialize = function; break; ++ case 11: clazz->__unserialize = function; break; ++#else + case 10: clazz->serialize_func = function; break; + case 11: clazz->unserialize_func = function; break; ++#endif + case 12: clazz->__debugInfo = function; break; + } + return; +@@ -148,7 +153,11 @@ zend_bool uopz_is_magic_method(zend_class_entry *clazz, zend_string *function) / + } /* }}} */ + + static inline int uopz_closure_equals(zval *closure, zend_function *function) { /* {{{ */ ++#if PHP_VERSION_ID >= 80000 ++ const zend_function *cmp = zend_get_closure_method_def(Z_OBJ_P(closure)); ++#else + const zend_function *cmp = zend_get_closure_method_def(closure); ++#endif + + if (cmp->common.prototype == function) { + return 1; +@@ -160,7 +169,8 @@ static inline int uopz_closure_equals(zval *closure, zend_function *function) { + int uopz_clean_function(zval *zv) { /* {{{ */ + zend_function *fp = Z_PTR_P(zv); + +- if (fp->type == ZEND_USER_FUNCTION) { ++ if (fp->type == ZEND_USER_FUNCTION && *((zend_op_array*)fp)->refcount > 1) { ++ + return ZEND_HASH_APPLY_REMOVE; + } + +diff --git a/tests/012.phpt b/tests/012.phpt +index 018a231..2f3c6b7 100644 +--- a/tests/012.phpt ++++ b/tests/012.phpt +@@ -82,7 +82,7 @@ string(%d) "string" + string(%d) "clone" + bool(true) + bool(true) +-string(50) "Call to private method Foo::priv() from context ''" ++string(%d) "Call to private method Foo::priv() from %s" + string(%d) "will not replace existing method %s::%s, use uopz_set_return instead" + string(%d) "will not replace existing function %s, use uopz_set_return instead" + string(%d) "__destruct" +diff --git a/tests/018.phpt b/tests/018.phpt +index 7d959bb..e570ca1 100644 +--- a/tests/018.phpt ++++ b/tests/018.phpt +@@ -15,7 +15,7 @@ const UOPZ_DEFINED = "DEFINED"; + + var_dump(uopz_undefine("UOPZ_DEFINED")); + +-var_dump(@constant("UOPZ_DEFINED")); ++var_dump(defined("UOPZ_DEFINED")); + + var_dump(FOO::BAR); + +@@ -39,7 +39,7 @@ try { + ?> + --EXPECT-- + bool(true) +-NULL ++bool(false) + int(1) + int(1) + bool(false) +diff --git a/tests/035.phpt b/tests/035.phpt +index 96c8141..70f52d2 100644 +--- a/tests/035.phpt ++++ b/tests/035.phpt +@@ -6,7 +6,7 @@ fetch class constant non existent class + + --EXPECTF-- + Fatal error: Uncaught Error: Class name must be a valid object or a string in %s:%d +diff --git a/tests/bugs/gh102.phpt b/tests/bugs/gh102.phpt +index 27d6ffc..74ede15 100644 +--- a/tests/bugs/gh102.phpt ++++ b/tests/bugs/gh102.phpt +@@ -16,7 +16,7 @@ uopz_undefine('Test\UNDEF'); + var_dump(Test\UNDEF); + ?> + --EXPECTF-- +-Fatal error: Uncaught Error: Undefined constant 'Test\UNDEF' in %s:7 ++Fatal error: Uncaught Error: Undefined constant %s in %s:7 + Stack trace: + #0 {main} + thrown in %s on line 7 +diff --git a/uopz.c b/uopz.c +index f6d9900..311ddc3 100644 +--- a/uopz.c ++++ b/uopz.c +@@ -651,7 +651,19 @@ static PHP_FUNCTION(uopz_allow_exit) { + + /* {{{ uopz_functions[] + */ +-#define UOPZ_FE(f) PHP_FE(f, NULL) ++#if PHP_VERSION_ID >= 80000 ++ZEND_BEGIN_ARG_INFO(uopz_ignore_arginfo, 1) ++ ZEND_ARG_VARIADIC_INFO(0, arguments) ++ZEND_END_ARG_INFO() ++# define UOPZ_FE(f) PHP_FE(f, uopz_ignore_arginfo) ++#else ++# define UOPZ_FE(f) PHP_FE(f, NULL) ++#endif ++ ++ZEND_BEGIN_ARG_INFO(uopz_no_args_arginfo, 0) ++ZEND_END_ARG_INFO() ++# define UOPZ_FE_NOARGS(f) PHP_FE(f, uopz_no_args_arginfo) ++ + static const zend_function_entry uopz_functions[] = { + UOPZ_FE(uopz_set_return) + UOPZ_FE(uopz_get_return) +@@ -673,7 +685,7 @@ static const zend_function_entry uopz_functions[] = { + UOPZ_FE(uopz_undefine) + UOPZ_FE(uopz_set_property) + UOPZ_FE(uopz_get_property) +- UOPZ_FE(uopz_get_exit_status) ++ UOPZ_FE_NOARGS(uopz_get_exit_status) + UOPZ_FE(uopz_allow_exit) + + UOPZ_FE(uopz_call_user_func) +-- +2.29.2 + +From 8ac783d8c151485b5bea8f917a654bb39e1a61d9 Mon Sep 17 00:00:00 2001 +From: Joe Watkins +Date: Thu, 1 Oct 2020 10:19:01 +0200 +Subject: [PATCH 6/7] fix that + +--- + src/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util.c b/src/util.c +index 311e1cb..fb10d7c 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -169,7 +169,7 @@ static inline int uopz_closure_equals(zval *closure, zend_function *function) { + int uopz_clean_function(zval *zv) { /* {{{ */ + zend_function *fp = Z_PTR_P(zv); + +- if (fp->type == ZEND_USER_FUNCTION && *((zend_op_array*)fp)->refcount > 1) { ++ if (fp->type == ZEND_USER_FUNCTION && (((zend_op_array*)fp)->refcount && *((zend_op_array*)fp)->refcount > 1)) { + + return ZEND_HASH_APPLY_REMOVE; + } +-- +2.29.2 + +From 7b0ed871029df6e58dfa071315f0979b0bc15868 Mon Sep 17 00:00:00 2001 +From: Remi Collet +Date: Fri, 5 Mar 2021 09:09:38 +0100 +Subject: [PATCH 7/7] missing uopz.disable=0 in test + +--- + tests/bugs/gh109.phpt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tests/bugs/gh109.phpt b/tests/bugs/gh109.phpt +index 5d440e4..6020366 100644 +--- a/tests/bugs/gh109.phpt ++++ b/tests/bugs/gh109.phpt +@@ -4,6 +4,8 @@ hook closure call inconsistency + ++--INI-- ++uopz.disable=0 + --FILE-- + opcode) { -- break; -- } -- if (zend_get_user_opcode_handler(handler->opcode) != handler->uopz) { -- UOPZ_HANDLER_OVERLOAD(handler); -- } -- handler++; -- } --} -- - void uopz_handlers_shutdown(void) { - uopz_vm_handler_t *handler = uopz_vm_handlers; - -diff --git a/src/handlers.h b/src/handlers.h -index 80574d3..6884faf 100644 ---- a/src/handlers.h -+++ b/src/handlers.h -@@ -20,7 +20,6 @@ - #define UOPZ_HANDLERS_H - - void uopz_handlers_init(void); --void uopz_handlers_update(void); - void uopz_handlers_shutdown(void); - - #endif /* UOPZ_HANDLERS_H */ -diff --git a/uopz.c b/uopz.c -index b181dda..2f8c193 100644 ---- a/uopz.c -+++ b/uopz.c -@@ -24,7 +24,6 @@ - #include "php_ini.h" - #include "ext/standard/info.h" - --#include "SAPI.h" - - #include "uopz.h" - -@@ -154,8 +152,6 @@ static PHP_RINIT_FUNCTION(uopz) - - uopz_request_init(); - -- uopz_handlers_update(); -- - return SUCCESS; - } /* }}} */ - - - -- cgit