]> granicus.if.org Git - php/commitdiff
Avoid non-object in FE_FREE
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 12 Oct 2020 07:38:59 +0000 (09:38 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 12 Oct 2020 07:45:52 +0000 (09:45 +0200)
Even if the properties HT is empty, make sure we still leave an
object in the FE_RESET result, so our type inference results
stay correct.

Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 6305ef8ef4649aaa727c2a3e05adb0b637ec12bf..bc7550f4ed80e9f3c906700949846758ae0cfcde 100644 (file)
@@ -6327,15 +6327,18 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
                        }
 
                        properties = Z_OBJPROP_P(array_ptr);
-                       if (zend_hash_num_elements(properties) == 0) {
-                               ZEND_VM_C_GOTO(fe_reset_r_empty);
-                       }
-
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (OP1_TYPE != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
+
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
+                               FREE_OP1_IF_VAR();
+                               ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+                       }
+
                        Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
                        FREE_OP1_IF_VAR();
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -6353,7 +6356,6 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
                }
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-ZEND_VM_C_LABEL(fe_reset_r_empty):
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
                FREE_OP1();
@@ -6427,6 +6429,7 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
                        properties = Z_OBJPROP_P(array_ptr);
                        if (zend_hash_num_elements(properties) == 0) {
                                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
+                               FREE_OP1_VAR_PTR();
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }
 
index 770f9667c95f4e43eaf9e38fe19dfec037fba339..0e65367eb5a791310b3ec729ee0e3a3dc62a5f05 100644 (file)
@@ -4150,15 +4150,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(
                        }
 
                        properties = Z_OBJPROP_P(array_ptr);
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
-
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_CONST != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
+
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
+
+                               ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+                       }
+
                        Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
 
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -4175,7 +4178,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(
                }
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
 
@@ -4249,6 +4251,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_
                        properties = Z_OBJPROP_P(array_ptr);
                        if (zend_hash_num_elements(properties) == 0) {
                                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
+
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }
 
@@ -18218,15 +18221,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE
                        }
 
                        properties = Z_OBJPROP_P(array_ptr);
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
-
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_TMP_VAR != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
+
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
+
+                               ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+                       }
+
                        Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
 
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -18244,7 +18250,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE
                }
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
                zval_ptr_dtor_nogc(free_op1);
@@ -18318,6 +18323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z
                        properties = Z_OBJPROP_P(array_ptr);
                        if (zend_hash_num_elements(properties) == 0) {
                                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
+
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }
 
@@ -21324,15 +21330,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE
                        }
 
                        properties = Z_OBJPROP_P(array_ptr);
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
-
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_VAR != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
+
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
+                               zval_ptr_dtor_nogc(free_op1);
+                               ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+                       }
+
                        Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
                        zval_ptr_dtor_nogc(free_op1);
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -21350,7 +21359,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE
                }
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
                zval_ptr_dtor_nogc(free_op1);
@@ -21424,6 +21432,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z
                        properties = Z_OBJPROP_P(array_ptr);
                        if (zend_hash_num_elements(properties) == 0) {
                                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
+                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }
 
@@ -37848,15 +37857,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN
                        }
 
                        properties = Z_OBJPROP_P(array_ptr);
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
-
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_CV != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
+
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
+
+                               ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
+                       }
+
                        Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
 
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -37873,7 +37885,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN
                }
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
-fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
 
@@ -37947,6 +37958,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE
                        properties = Z_OBJPROP_P(array_ptr);
                        if (zend_hash_num_elements(properties) == 0) {
                                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
+
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }