]> granicus.if.org Git - php/commitdiff
JIT support for undefined index/offset handling
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 13:09:12 +0000 (15:09 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 13:13:03 +0000 (15:13 +0200)
Zend/zend_execute.c
Zend/zend_execute.h
ext/opcache/jit/zend_jit_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index bd4ce8fa7e685fb14bcdfee8ea8846822d6d6e55..69a9afecc17ac062198bc6a973a7f053e96ded9c 100644 (file)
@@ -1909,8 +1909,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const
        zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset));
 }
 
-static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write(
-               HashTable *ht, zend_long lval)
+ZEND_API ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht, zend_long lval)
 {
        /* The array may be destroyed while throwing the notice.
         * Temporarily increase the refcount to detect this situation. */
@@ -1928,8 +1927,7 @@ static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write
        return SUCCESS;
 }
 
-static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_index_write(
-               HashTable *ht, zend_string *offset)
+ZEND_API ZEND_COLD int ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, zend_string *offset)
 {
        /* The array may be destroyed while throwing the notice.
         * Temporarily increase the refcount to detect this situation. */
index 7b1ae117489918aba1ec688bafcc9f7a3b74f7c6..84fd23e610995fb933351ca85cd8651d2d1023de 100644 (file)
@@ -64,6 +64,8 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert
 
 ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(zend_property_info *prop, zval *zv);
 ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(zend_property_info *prop1, zend_property_info *prop2, zval *zv);
+ZEND_API ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht, zend_long lval);
+ZEND_API ZEND_COLD int ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, zend_string *offset);
 
 ZEND_API zend_bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, zend_bool strict, zend_bool is_internal_arg);
 ZEND_API ZEND_COLD void zend_verify_arg_error(
index 3d40e745d17a566a1e82aee1f854e44e779f0086..c0fa257ed9c28f218f5df35e942821a7bf44e0fb 100644 (file)
@@ -129,8 +129,10 @@ static zval* ZEND_FASTCALL zend_jit_hash_index_lookup_rw(HashTable *ht, zend_lon
        zval *retval = _zend_hash_index_find(ht, idx);
 
        if (!retval) {
-               zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, idx);
-               retval = zend_hash_index_update(ht, idx, &EG(uninitialized_zval));
+               if (UNEXPECTED(zend_undefined_offset_write(ht, idx) == FAILURE)) {
+                       return NULL;
+               }
+               retval = zend_hash_index_add_new(ht, idx, &EG(uninitialized_zval));
        }
        return retval;
 }
@@ -153,12 +155,16 @@ static zval* ZEND_FASTCALL zend_jit_hash_lookup_rw(HashTable *ht, zend_string *s
                if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
                        retval = Z_INDIRECT_P(retval);
                        if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
-                               zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(str));
+                               if (UNEXPECTED(zend_undefined_index_write(ht, str) == FAILURE)) {
+                                       return NULL;
+                               }
                                ZVAL_NULL(retval);
                        }
                }
        } else {
-               zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(str));
+               if (UNEXPECTED(zend_undefined_index_write(ht, str) == FAILURE)) {
+                       return NULL;
+               }
                retval = zend_hash_update(ht, str, &EG(uninitialized_zval));
        }
        return retval;
@@ -202,8 +208,10 @@ static zval* ZEND_FASTCALL zend_jit_symtable_lookup_rw(HashTable *ht, zend_strin
                if (_zend_handle_numeric_str_ex(str->val, str->len, &idx)) {
                        retval = zend_hash_index_find(ht, idx);
                        if (!retval) {
-                               zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(str));
-                               retval = zend_hash_index_update(ht, idx, &EG(uninitialized_zval));
+                               if (UNEXPECTED(zend_undefined_index_write(ht, str) == FAILURE)) {
+                                       return NULL;
+                               }
+                               retval = zend_hash_index_add_new(ht, idx, &EG(uninitialized_zval));
                        }
                        return retval;
                }
@@ -214,13 +222,17 @@ static zval* ZEND_FASTCALL zend_jit_symtable_lookup_rw(HashTable *ht, zend_strin
                if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
                        retval = Z_INDIRECT_P(retval);
                        if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
-                               zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(str));
+                               if (UNEXPECTED(zend_undefined_index_write(ht, str) == FAILURE)) {
+                                       return NULL;
+                               }
                                ZVAL_NULL(retval);
                        }
                }
        } else {
-               zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(str));
-               retval = zend_hash_update(ht, str, &EG(uninitialized_zval));
+               if (UNEXPECTED(zend_undefined_index_write(ht, str) == FAILURE)) {
+                       return NULL;
+               }
+               retval = zend_hash_add_new(ht, str, &EG(uninitialized_zval));
        }
        return retval;
 }
@@ -531,13 +543,17 @@ str_index:
                if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
                        retval = Z_INDIRECT_P(retval);
                        if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
-                               zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
+                               if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
+                                       return NULL;
+                               }
                                ZVAL_NULL(retval);
                        }
                }
        } else {
-               zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
-               retval = zend_hash_update(ht, offset_key, &EG(uninitialized_zval));
+               if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
+                       return NULL;
+               }
+               retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
        }
        return retval;
 
@@ -546,8 +562,10 @@ num_index:
        return retval;
 
 num_undef:
-       zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
-       retval = zend_hash_index_update(ht, hval, &EG(uninitialized_zval));
+       if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
+               return NULL;
+       }
+       retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
        return retval;
 }
 
index feabefba4de499473e829e58e25d54067cf292ad..b9066f465dfc93b254847ad30e1404e2aee90e51 100644 (file)
@@ -4976,6 +4976,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
                                        |4:
                                        |       SAVE_VALID_OPLINE opline, r0
                                        |       EXT_CALL zend_jit_hash_index_lookup_rw, r0
+                                       |       test r0, r0
+                                       |       jz >9
                                }
                                break;
                        case BP_VAR_W:
@@ -5099,6 +5101,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
                                } else {
                                        |       EXT_CALL zend_jit_hash_lookup_rw, r0
                                }
+                               |       test r0, r0
+                               |       jz >9
                                break;
                        case BP_VAR_W:
                                if (opline->op2_type != IS_CONST) {