]> granicus.if.org Git - php/commitdiff
Fixed bug #70083 (Use after free with assign by ref on overloaded objects)
authorBob Weinand <bobwei9@hotmail.com>
Wed, 15 Jul 2015 20:36:42 +0000 (22:36 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Wed, 15 Jul 2015 20:36:42 +0000 (22:36 +0200)
NEWS
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index eca537c597f93f2aee01cea08fdc34a87b7cfe76..d29234b5b5635d831017dc5cb1ee78c839a22aea 100644 (file)
--- 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)
index 98a7f2785bfff7a52980b3065f21a0b68fcae536..27841eb119087c5ff4edb6dcb5006f06c45353ff 100644 (file)
@@ -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)
 
index 13863d0dcb0a3ef32929be86ac8281a45a9ff4c4..7d74e8378f478033d5063a51b3828d80d467f772 100644 (file)
@@ -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);
index a229ba8f73311c66acbb6aa91d074c0bfbb7d646..8dba75dec573fe2cfee8a38a6bb7d64b1dc9f4dc 100644 (file)
@@ -18393,12 +18393,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE
                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");
+               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);
@@ -36587,12 +36584,19 @@ 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)) {
@@ -36606,14 +36610,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(
        if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
                zend_throw_error(NULL, "Cannot create references to/from string offsets nor overloaded objects");
 
-               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))) ||