summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2015-07-15 22:36:42 +0200
committerBob Weinand <bobwei9@hotmail.com>2015-07-15 22:36:42 +0200
commit0af07333520f65def3a72f31effa38c907e962f9 (patch)
tree1c461c81560f7e5cd2b6b8709f258e126332d039
parentd25f3819c70888d791eb8031e5049d0791c1b040 (diff)
downloadphp-git-0af07333520f65def3a72f31effa38c907e962f9.tar.gz
Fixed bug #70083 (Use after free with assign by ref on overloaded objects)
-rw-r--r--NEWS2
-rw-r--r--Zend/zend_execute.c3
-rw-r--r--Zend/zend_vm_def.h19
-rw-r--r--Zend/zend_vm_execute.h76
4 files changed, 47 insertions, 53 deletions
diff --git a/NEWS b/NEWS
index eca537c597..d29234b5b5 100644
--- a/NEWS
+++ b/NEWS
@@ -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);