From 8012a1dd9955a2a52f630f2dc4763c53304efbef Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Wed, 2 Aug 2023 16:13:09 +0100 Subject: [PATCH 1/2] Zend: Fix memory leak in ++/-- when overloading fetch access --- .../in-de-crement/overloaded_access.phpt | 36 +++++++++++++++++++ Zend/zend_vm_def.h | 6 ++-- Zend/zend_vm_execute.h | 12 ++++--- 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/in-de-crement/overloaded_access.phpt diff --git a/Zend/tests/in-de-crement/overloaded_access.phpt b/Zend/tests/in-de-crement/overloaded_access.phpt new file mode 100644 index 0000000000000..56a5c2b1d47a0 --- /dev/null +++ b/Zend/tests/in-de-crement/overloaded_access.phpt @@ -0,0 +1,36 @@ +--TEST-- +Overloaded array access with pre increment/decrement +--FILE-- +getMessage() . "\n"; +} +$foo = new Foo; +try { + $foo[0]--; +} catch (Throwable $ex) { + echo $ex->getMessage() . "\n"; +} +?> +--EXPECT-- +Cannot increment array +Cannot decrement array diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1a95059020018..b590a13cc81dc 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1501,7 +1501,8 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) } increment_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + FREE_OP1(); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -1560,7 +1561,8 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) } decrement_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + FREE_OP1(); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 881dec2d9d3fd..5f1594bfe24b6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -21625,7 +21625,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } increment_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -21702,7 +21703,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } decrement_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -39008,7 +39010,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } increment_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -39084,7 +39087,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } decrement_function(var_ptr); if (UNEXPECTED(EG(exception))) { - /* Smart branch expects result to be set with exceptions */ + + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } From 3827a508bd5e0a47c968e9e7a0422ee55f4b2d3d Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Wed, 2 Aug 2023 16:24:07 +0100 Subject: [PATCH 2/2] Drop now duplicate code --- Zend/zend_vm_def.h | 18 ++---------------- Zend/zend_vm_execute.h | 36 ++++-------------------------------- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b590a13cc81dc..416725788836f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1500,16 +1500,9 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) } } increment_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - FREE_OP1(); - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -1560,16 +1553,9 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) } } decrement_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - FREE_OP1(); - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5f1594bfe24b6..893f727c26837 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -21624,16 +21624,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } } increment_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -21702,16 +21695,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } } decrement_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -39009,16 +38995,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } } increment_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -39086,16 +39065,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } } decrement_function(var_ptr); - if (UNEXPECTED(EG(exception))) { - - /* opcodes are expected to set the result value */ - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - HANDLE_EXCEPTION(); - } } while (0); + /* opcodes are expected to set the result value */ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); }