diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 3 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 19 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 76 |
4 files changed, 47 insertions, 53 deletions
@@ -8,6 +8,8 @@ . Fixed bug #70012 (Exception lost with nested finally block). (Laruence) . Fixed bug #69996 (Changing the property of a cloned object affects the original). (Dmitry, Laruence) + . Fixed bug #70083 (Use after free with assign by ref to overloaded objects). + (Bob) - Curl: . Fixed bug #70065 (curl_getinfo() returns corrupted values). (Anatol) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 98a7f2785b..27841eb119 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -88,9 +88,6 @@ static const zend_internal_function zend_pass_function = { #undef zval_ptr_dtor #define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC) -#define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z)) -#define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); } - #define READY_TO_DESTROY(zv) \ (zv && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 13863d0dcb..7d74e8378f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2267,12 +2267,19 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) FREE_UNFETCHED_OP1(); HANDLE_EXCEPTION(); } + if (OP1_TYPE == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + FREE_OP2_VAR_PTR(); + HANDLE_EXCEPTION(); + } if (OP2_TYPE == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!OP2_FREE) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + if (!OP2_FREE && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ + Z_TRY_ADDREF_P(value_ptr); } zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -2288,14 +2295,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) FREE_OP2_VAR_PTR(); HANDLE_EXCEPTION(); } - if (OP1_TYPE == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - FREE_OP2_VAR_PTR(); - FREE_OP1_VAR_PTR(); - HANDLE_EXCEPTION(); - } if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a229ba8f73..8dba75dec5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -18394,11 +18394,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } + if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + if (!(free_op2 != NULL) && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ + Z_TRY_ADDREF_P(value_ptr); } zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -18414,14 +18421,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); } - if (IS_VAR == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - HANDLE_EXCEPTION(); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -20615,12 +20614,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + + HANDLE_EXCEPTION(); + } if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!0) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + if (!0 && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ + Z_TRY_ADDREF_P(value_ptr); } zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -20636,14 +20642,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER HANDLE_EXCEPTION(); } - if (IS_VAR == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; - HANDLE_EXCEPTION(); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -33235,12 +33233,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER HANDLE_EXCEPTION(); } + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL)) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + if (!(free_op2 != NULL) && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ + Z_TRY_ADDREF_P(value_ptr); } zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -33256,14 +33261,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); } - if (IS_CV == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; - - HANDLE_EXCEPTION(); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -36588,11 +36585,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!0) { - PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ + if (!0 && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ + Z_TRY_ADDREF_P(value_ptr); } zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -36608,14 +36612,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( HANDLE_EXCEPTION(); } - if (IS_CV == IS_VAR && - UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - - - HANDLE_EXCEPTION(); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); |