From: Nikita Popov Date: Tue, 7 Jul 2020 13:09:12 +0000 (+0200) Subject: JIT support for undefined index/offset handling X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cdc4ea2a5c1dbcdf8e8c885152b783d039e01b53;p=php JIT support for undefined index/offset handling --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bd4ce8fa7e..69a9afecc1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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. */ diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 7b1ae11748..84fd23e610 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -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( diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 3d40e745d1..c0fa257ed9 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -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; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index feabefba4d..b9066f465d 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -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) {