]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.4' into PHP-8.0
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 12 Oct 2020 07:46:38 +0000 (09:46 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 12 Oct 2020 07:46:38 +0000 (09:46 +0200)
* PHP-7.4:
  Avoid non-object in FE_FREE

1  2 
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 930cd342e80e332017d740ea1f85924ce55060d1,bc7550f4ed80e9f3c906700949846758ae0cfcde..d647dddeab03dab980205423fdf0852dbe99c0f6
@@@ -6482,24 -6316,17 +6482,20 @@@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CO
                FREE_OP1_IF_VAR();
                ZEND_VM_NEXT_OPCODE();
        } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
 -              if (!Z_OBJCE_P(array_ptr)->get_iterator) {
 -                      HashTable *properties;
 -                      if (Z_OBJ_P(array_ptr)->properties
 -                       && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
 -                              if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
 -                                      GC_DELREF(Z_OBJ_P(array_ptr)->properties);
 +              zend_object *zobj = Z_OBJ_P(array_ptr);
 +              if (!zobj->ce->get_iterator) {
 +                      HashTable *properties = zobj->properties;
 +                      if (properties) {
 +                              if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
 +                                      if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
 +                                              GC_DELREF(properties);
 +                                      }
 +                                      properties = zobj->properties = zend_array_dup(properties);
                                }
 -                              Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
 +                      } else {
 +                              properties = zobj->handlers->get_properties(zobj);
                        }
  
-                       if (zend_hash_num_elements(properties) == 0) {
-                               ZEND_VM_C_GOTO(fe_reset_r_empty);
-                       }
 -                      properties = Z_OBJPROP_P(array_ptr);
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (OP1_TYPE != IS_TMP_VAR) {
                        }
                }
        } else {
 -              zend_error(E_WARNING, "Invalid argument supplied for foreach()");
 +              zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
- 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();
index e180c28c7528be14bb8dffa518401a6ed52c7601,0e65367eb5a791310b3ec729ee0e3a3dc62a5f05..27d1ee15719a77961185276aa4d82122fc1953fe
@@@ -4791,24 -4139,17 +4791,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS
  
                ZEND_VM_NEXT_OPCODE();
        } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
 -              if (!Z_OBJCE_P(array_ptr)->get_iterator) {
 -                      HashTable *properties;
 -                      if (Z_OBJ_P(array_ptr)->properties
 -                       && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
 -                              if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
 -                                      GC_DELREF(Z_OBJ_P(array_ptr)->properties);
 +              zend_object *zobj = Z_OBJ_P(array_ptr);
 +              if (!zobj->ce->get_iterator) {
 +                      HashTable *properties = zobj->properties;
 +                      if (properties) {
 +                              if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
 +                                      if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
 +                                              GC_DELREF(properties);
 +                                      }
 +                                      properties = zobj->properties = zend_array_dup(properties);
                                }
 -                              Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
 +                      } else {
 +                              properties = zobj->handlers->get_properties(zobj);
                        }
  
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
 -                      properties = Z_OBJPROP_P(array_ptr);
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_CONST != IS_TMP_VAR) {
                        }
                }
        } else {
 -              zend_error(E_WARNING, "Invalid argument supplied for foreach()");
 +              zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
- fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
  
@@@ -18798,24 -18210,17 +18801,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS
  
                ZEND_VM_NEXT_OPCODE();
        } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
 -              if (!Z_OBJCE_P(array_ptr)->get_iterator) {
 -                      HashTable *properties;
 -                      if (Z_OBJ_P(array_ptr)->properties
 -                       && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
 -                              if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
 -                                      GC_DELREF(Z_OBJ_P(array_ptr)->properties);
 +              zend_object *zobj = Z_OBJ_P(array_ptr);
 +              if (!zobj->ce->get_iterator) {
 +                      HashTable *properties = zobj->properties;
 +                      if (properties) {
 +                              if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
 +                                      if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
 +                                              GC_DELREF(properties);
 +                                      }
 +                                      properties = zobj->properties = zend_array_dup(properties);
                                }
 -                              Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
 +                      } else {
 +                              properties = zobj->handlers->get_properties(zobj);
                        }
  
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
 -                      properties = Z_OBJPROP_P(array_ptr);
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_TMP_VAR != IS_TMP_VAR) {
                        }
                }
        } else {
 -              zend_error(E_WARNING, "Invalid argument supplied for foreach()");
 +              zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
- 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);
 +              zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
        }
  }
@@@ -21357,34 -21316,34 +21363,37 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS
                }
                Z_FE_POS_P(result) = 0;
  
 -              zval_ptr_dtor_nogc(free_op1);
 +              zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
                ZEND_VM_NEXT_OPCODE();
        } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
 -              if (!Z_OBJCE_P(array_ptr)->get_iterator) {
 -                      HashTable *properties;
 -                      if (Z_OBJ_P(array_ptr)->properties
 -                       && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
 -                              if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
 -                                      GC_DELREF(Z_OBJ_P(array_ptr)->properties);
 +              zend_object *zobj = Z_OBJ_P(array_ptr);
 +              if (!zobj->ce->get_iterator) {
 +                      HashTable *properties = zobj->properties;
 +                      if (properties) {
 +                              if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
 +                                      if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
 +                                              GC_DELREF(properties);
 +                                      }
 +                                      properties = zobj->properties = zend_array_dup(properties);
                                }
 -                              Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
 +                      } else {
 +                              properties = zobj->handlers->get_properties(zobj);
                        }
  
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
 -                      properties = Z_OBJPROP_P(array_ptr);
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_VAR != IS_TMP_VAR) {
                                Z_ADDREF_P(array_ptr);
                        }
 -                              zval_ptr_dtor_nogc(free_op1);
+                       if (zend_hash_num_elements(properties) == 0) {
+                               Z_FE_ITER_P(result) = (uint32_t) -1;
++                              zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
+                               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);
 +                      zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
                        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
                } else {
                        zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC);
                        }
                }
        } else {
 -              zend_error(E_WARNING, "Invalid argument supplied for foreach()");
 +              zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
- 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);
 +              zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
        }
  }
@@@ -21473,6 -21432,7 +21481,7 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS
                        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);};
++                              zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
                                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
                        }
  
@@@ -38072,24 -37846,17 +38081,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS
  
                ZEND_VM_NEXT_OPCODE();
        } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
 -              if (!Z_OBJCE_P(array_ptr)->get_iterator) {
 -                      HashTable *properties;
 -                      if (Z_OBJ_P(array_ptr)->properties
 -                       && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
 -                              if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
 -                                      GC_DELREF(Z_OBJ_P(array_ptr)->properties);
 +              zend_object *zobj = Z_OBJ_P(array_ptr);
 +              if (!zobj->ce->get_iterator) {
 +                      HashTable *properties = zobj->properties;
 +                      if (properties) {
 +                              if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
 +                                      if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
 +                                              GC_DELREF(properties);
 +                                      }
 +                                      properties = zobj->properties = zend_array_dup(properties);
                                }
 -                              Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
 +                      } else {
 +                              properties = zobj->handlers->get_properties(zobj);
                        }
  
-                       if (zend_hash_num_elements(properties) == 0) {
-                               goto fe_reset_r_empty;
-                       }
 -                      properties = Z_OBJPROP_P(array_ptr);
                        result = EX_VAR(opline->result.var);
                        ZVAL_COPY_VALUE(result, array_ptr);
                        if (IS_CV != IS_TMP_VAR) {
                        }
                }
        } else {
 -              zend_error(E_WARNING, "Invalid argument supplied for foreach()");
 +              zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
- fe_reset_r_empty:
                ZVAL_UNDEF(EX_VAR(opline->result.var));
                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;