diff --git a/Zend/tests/in-de-crement/object_cannot_incdec.phpt b/Zend/tests/in-de-crement/object_cannot_incdec.phpt new file mode 100644 index 00000000000..39a41d61dd3 --- /dev/null +++ b/Zend/tests/in-de-crement/object_cannot_incdec.phpt @@ -0,0 +1,45 @@ +--TEST-- +Cannot increment/decrement objects +--FILE-- +getMessage(), PHP_EOL; + var_dump($o); +} +try { + $o--; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +try { + ++$o; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +try { + --$o; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +?> +--EXPECT-- +Cannot increment Foo +object(Foo)#1 (0) { +} +Cannot decrement Foo +object(Foo)#1 (0) { +} +Cannot increment Foo +object(Foo)#1 (0) { +} +Cannot decrement Foo +object(Foo)#1 (0) { +} diff --git a/Zend/tests/in-de-crement/object_cannot_incdec_use_result_op.phpt b/Zend/tests/in-de-crement/object_cannot_incdec_use_result_op.phpt new file mode 100644 index 00000000000..b4c193a6718 --- /dev/null +++ b/Zend/tests/in-de-crement/object_cannot_incdec_use_result_op.phpt @@ -0,0 +1,45 @@ +--TEST-- +Cannot increment/decrement objects +--FILE-- +getMessage(), PHP_EOL; + var_dump($o); +} +try { + $y = $o--; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +try { + $y = ++$o; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +try { + $y = --$o; +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + var_dump($o); +} +?> +--EXPECT-- +Cannot increment Foo +object(Foo)#1 (0) { +} +Cannot decrement Foo +object(Foo)#1 (0) { +} +Cannot increment Foo +object(Foo)#1 (0) { +} +Cannot decrement Foo +object(Foo)#1 (0) { +} diff --git a/Zend/tests/in-de-crement/oss-fuzz-60734_predec-object.phpt b/Zend/tests/in-de-crement/oss-fuzz-60734_predec-object.phpt new file mode 100644 index 00000000000..0f0e19c8c2d --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-60734_predec-object.phpt @@ -0,0 +1,14 @@ +--TEST-- +OSS Fuzz #60734: use-after-free visible in ASAN build pre decrement. +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot decrement Foo in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/in-de-crement/oss-fuzz-60734_preinc-object.phpt b/Zend/tests/in-de-crement/oss-fuzz-60734_preinc-object.phpt new file mode 100644 index 00000000000..3bae551f04f --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-60734_preinc-object.phpt @@ -0,0 +1,14 @@ +--TEST-- +OSS Fuzz #60734: use-after-free visible in ASAN build pre increment. +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot increment Foo in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b2e3e60a294..1a950590200 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1501,6 +1501,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0); @@ -1556,6 +1560,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1db9b06a178..881dec2d9d3 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -21625,6 +21625,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0); @@ -21698,6 +21702,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0); @@ -39000,6 +39008,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0); @@ -39072,6 +39084,10 @@ 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 */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } HANDLE_EXCEPTION(); } } while (0);