JIT support for undefined index/offset handling

This commit is contained in:
Nikita Popov 2020-07-07 15:09:12 +02:00
parent f497b69944
commit cdc4ea2a5c
4 changed files with 40 additions and 18 deletions

View 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. */

View 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(

View 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;
}

View 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) {