diff --git a/src/handlers.c b/src/handlers.c index b5ffade..2d0e8e0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -29,7 +29,7 @@ ZEND_EXTERN_MODULE_GLOBALS(uopz); -#define UOPZ_HANDLERS_COUNT 12 +#define UOPZ_HANDLERS_COUNT 13 #ifdef ZEND_VM_FP_GLOBAL_REG # define UOPZ_OPCODE_HANDLER_ARGS @@ -99,6 +99,7 @@ typedef struct _uopz_vm_handler_t { } uopz_vm_handler_t; zend_vm_handler_t zend_vm_exit; +zend_vm_handler_t zend_vm_verify_never_type; zend_vm_handler_t zend_vm_new; zend_vm_handler_t zend_vm_fetch_constant; zend_vm_handler_t zend_vm_do_fcall; @@ -112,6 +113,7 @@ zend_vm_handler_t zend_vm_init_method_call; zend_vm_handler_t zend_vm_init_static_method_call; int uopz_vm_exit(UOPZ_OPCODE_HANDLER_ARGS); +int uopz_vm_verify_never_type(UOPZ_OPCODE_HANDLER_ARGS); int uopz_vm_new(UOPZ_OPCODE_HANDLER_ARGS); int uopz_vm_fetch_constant(UOPZ_OPCODE_HANDLER_ARGS); int uopz_vm_do_fcall(UOPZ_OPCODE_HANDLER_ARGS); @@ -125,6 +127,7 @@ int uopz_vm_init_static_method_call(UOPZ_OPCODE_HANDLER_ARGS); UOPZ_HANDLERS_DECL_BEGIN() UOPZ_HANDLER_DECL(ZEND_EXIT, exit) + UOPZ_HANDLER_DECL(ZEND_VERIFY_NEVER_TYPE, verify_never_type) UOPZ_HANDLER_DECL(ZEND_NEW, new) UOPZ_HANDLER_DECL(ZEND_FETCH_CONSTANT, fetch_constant) UOPZ_HANDLER_DECL(ZEND_FETCH_CLASS_CONSTANT, fetch_class_constant) @@ -155,7 +158,7 @@ void uopz_handlers_init(void) { void uopz_handlers_shutdown(void) { uopz_vm_handler_t *handler = uopz_vm_handlers; - + while (handler) { if (!handler->opcode) { break; @@ -173,6 +176,10 @@ static zend_always_inline int _uopz_vm_dispatch(UOPZ_OPCODE_HANDLER_ARGS) { zend = zend_vm_exit; break; + case ZEND_VERIFY_NEVER_TYPE: + zend = zend_vm_verify_never_type; + break; + case ZEND_NEW: zend = zend_vm_new; break; @@ -195,7 +202,7 @@ static zend_always_inline int _uopz_vm_dispatch(UOPZ_OPCODE_HANDLER_ARGS) { case ZEND_INIT_STATIC_METHOD_CALL: zend = zend_vm_init_static_method_call; - break; + break; case ZEND_FETCH_CONSTANT: zend = zend_vm_fetch_constant; @@ -267,6 +274,12 @@ int uopz_vm_exit(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ } } /* }}} */ +int uopz_vm_verify_never_type(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ + if (UOPZ(exit)) { + UOPZ_VM_DISPATCH(); + } else UOPZ_VM_RETURN(); +} /* }}} */ + int uopz_vm_new(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ UOPZ_USE_OPLINE; zval *result; @@ -274,7 +287,7 @@ int uopz_vm_new(UOPZ_OPCODE_HANDLER_ARGS) { /* {{{ */ zend_class_entry *ce; zend_execute_data *call; zend_object *obj = NULL; - + UOPZ_SAVE_OPLINE(); if (opline->op1_type == IS_CONST) { diff --git a/src/handlers.h b/src/handlers.h index 85eeaf9..db3a4d9 100644 --- a/src/handlers.h +++ b/src/handlers.h @@ -22,6 +22,10 @@ void uopz_handlers_init(void); void uopz_handlers_shutdown(void); +#ifndef ZEND_VERIFY_RETURN_TYPE +#define ZEND_VERIFY_RETURN_TYPE 124 +#endif + #endif /* UOPZ_HANDLERS_H */ /* diff --git a/tests/bugs/gh172.phpt b/tests/bugs/gh172.phpt new file mode 100644 index 0000000..da60704 --- /dev/null +++ b/tests/bugs/gh172.phpt @@ -0,0 +1,29 @@ +--TEST-- +handle ZEND_VERIFY_NEVER_TYPE when uopz.exit disabled +--EXTENSIONS-- +uopz +--INI-- +uopz.disable=0 +uopz.exit=0 +opcache.enable_cli=0 +xdebug.enable=0 +--FILE-- + +--EXPECT-- +int(10) \ No newline at end of file diff --git a/tests/bugs/gh172a.phpt b/tests/bugs/gh172a.phpt new file mode 100644 index 0000000..2120931 --- /dev/null +++ b/tests/bugs/gh172a.phpt @@ -0,0 +1,20 @@ +--TEST-- +do not handle ZEND_VERIFY_NEVER_TYPE if not uopz_allow_exit +--EXTENSIONS-- +uopz +--INI-- +uopz.disable=0 +uopz.exit=1 +opcache.enable_cli=0 +xdebug.enable=0 +--FILE-- + +--EXPECTF-- +Fatal error: A never-returning function must not return in %s \ No newline at end of file