Skip to content

Use common function for TypeError on illegal offset access #10544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Zend/tests/036.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ try {

?>
--EXPECT--
Cannot access offset of type object on array
Cannot access offset of type Closure on array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a question, not a suggestion: What do you think of also specifying what is allowed? Array offset must be int or string, cannot access offset of type Closure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can only really do this for arrays and strings :/ as objects that implement ArrayOffset can in theory support any type

2 changes: 1 addition & 1 deletion Zend/tests/038.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ try {

?>
--EXPECT--
Cannot access offset of type object on array
Cannot access offset of type Closure on array
4 changes: 2 additions & 2 deletions Zend/tests/assign_dim_obj_null_return.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ test();
--EXPECT--
Cannot add element to the array as the next element is already occupied
Cannot access offset of type array on array
Cannot access offset of type object on array
Cannot access offset of type stdClass on array
Cannot use a scalar value as an array
Cannot add element to the array as the next element is already occupied
Cannot access offset of type array on array
Cannot access offset of type object on array
Cannot access offset of type stdClass on array
Cannot use a scalar value as an array
Attempt to assign property "foo" on true
Attempt to assign property "foo" on true
2 changes: 1 addition & 1 deletion Zend/tests/bug24773.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Bug #24773 (unset() of integers treated as arrays causes a crash)
unset($array["lvl1"]["lvl2"]["b"]);
?>
--EXPECTF--
Fatal error: Uncaught TypeError: Cannot access offset of type string on string in %s:%d
Fatal error: Uncaught Error: Cannot unset string offsets in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/gh8821.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ new Bravo();

?>
--EXPECTF--
Fatal error: Uncaught TypeError: Cannot access offset of type object on array in %sgh8821.php:8
Fatal error: Uncaught TypeError: Cannot access offset of type Alpha on array in %sgh8821.php:8
Stack trace:
#0 %sgh8821.php(11): [constant expression]()
#1 {main}
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/illegal_offset_unset_isset_empty.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ try {

?>
--EXPECT--
Cannot access offset of type array in unset
Cannot unset offset of type array on array
Cannot access offset of type array in isset or empty
Cannot access offset of type array in isset or empty
2 changes: 1 addition & 1 deletion Zend/tests/init_array_illegal_offset_type.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ try {
}
?>
--EXPECT--
Cannot access offset of type object on array
Cannot access offset of type stdClass on array
2 changes: 1 addition & 1 deletion Zend/tests/isset_array.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ bool(false)
Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
bool(false)
Cannot access offset of type array in isset or empty
Cannot access offset of type object in isset or empty
Cannot access offset of type stdClass in isset or empty
2 changes: 1 addition & 1 deletion Zend/tests/offset_array.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ int(1)

Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
int(%d)
Cannot access offset of type object on array
Cannot access offset of type stdClass on array
Cannot access offset of type array on array
Done
23 changes: 23 additions & 0 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,29 @@ ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const c
}
/* }}} */

/* type should be one of the BP_VAR_* constants, only special messages happen for isset/empty and unset */
ZEND_API ZEND_COLD void zend_illegal_container_offset(const zend_string *container, const zval *offset, int type)
{
switch (type) {
case BP_VAR_IS:
zend_type_error("Cannot access offset of type %s in isset or empty",
zend_zval_type_name(offset));
return;
case BP_VAR_UNSET:
/* Consistent error for when trying to unset a string offset */
if (zend_string_equals(container, ZSTR_KNOWN(ZEND_STR_STRING))) {
zend_throw_error(NULL, "Cannot unset string offsets");
} else {
zend_type_error("Cannot unset offset of type %s on %s", zend_zval_type_name(offset), ZSTR_VAL(container));
}
return;
default:
zend_type_error("Cannot access offset of type %s on %s",
zend_zval_type_name(offset), ZSTR_VAL(container));
return;
}
}

ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */
{
va_list va;
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const c
ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
ZEND_API ZEND_COLD void zend_value_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
/* type should be one of the BP_VAR_* constants, only special messages happen for isset/empty and unset */
ZEND_API ZEND_COLD void zend_illegal_container_offset(const zend_string *container, const zval *offset, int type);

ZEND_COLD void zenderror(const char *error);

Expand Down
12 changes: 1 addition & 11 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,16 +407,6 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_en
}
/* }}} */

ZEND_API ZEND_COLD void zend_illegal_array_offset(const zval *offset)
{
zend_type_error("Cannot access offset of type %s on array", zend_get_type_by_const(Z_TYPE_P(offset)));
}

ZEND_API ZEND_COLD void zend_illegal_empty_or_isset_offset(const zval *offset)
{
zend_type_error("Cannot access offset of type %s in isset or empty", zend_get_type_by_const(Z_TYPE_P(offset)));
}

ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
{
va_list va;
Expand Down Expand Up @@ -2112,7 +2102,7 @@ ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) /
result = zend_hash_index_update(ht, zend_dval_to_lval_safe(Z_DVAL_P(key)), value);
break;
default:
zend_illegal_array_offset(key);
zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), key, BP_VAR_W);
result = NULL;
}

Expand Down
32 changes: 16 additions & 16 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -1506,24 +1506,24 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(v
zend_throw_error(NULL, "Cannot use object as array");
}

static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_unset_offset(const zval *offset)
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_access(const zval *offset)
{
zend_type_error("Cannot access offset of type %s in unset", zend_get_type_by_const(Z_TYPE_P(offset)));
zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_RW);
}

static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset(const zval *offset)
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_isset(const zval *offset)
{
zend_type_error("Cannot access offset of type %s on array", zend_get_type_by_const(Z_TYPE_P(offset)));
zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_IS);
}

static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_empty_or_isset_offset(const zval *offset)
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_unset(const zval *offset)
{
zend_type_error("Cannot access offset of type %s in isset or empty", zend_get_type_by_const(Z_TYPE_P(offset)));
zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_ARRAY), offset, BP_VAR_UNSET);
}

static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_string_offset(const zval *offset)
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_string_offset(const zval *offset, int type)
{
zend_type_error("Cannot access offset of type %s on string", zend_zval_type_name(offset));
zend_illegal_container_offset(ZSTR_KNOWN(ZEND_STR_STRING), offset, type);
}

static zend_never_inline void zend_assign_to_object_dim(zend_object *obj, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
Expand Down Expand Up @@ -1651,7 +1651,7 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type
}
return offset;
}
zend_illegal_string_offset(dim);
zend_illegal_string_offset(dim, type);
return 0;
}
case IS_UNDEF:
Expand All @@ -1667,7 +1667,7 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type
dim = Z_REFVAL_P(dim);
goto try_again;
default:
zend_illegal_string_offset(dim);
zend_illegal_string_offset(dim, type);
return 0;
}

Expand Down Expand Up @@ -2390,7 +2390,7 @@ static zend_never_inline uint8_t slow_index_convert(HashTable *ht, const zval *d
value->lval = 1;
return IS_LONG;
default:
zend_illegal_array_offset(dim);
zend_illegal_array_offset_access(dim);
return IS_NULL;
}
}
Expand Down Expand Up @@ -2464,7 +2464,7 @@ static zend_never_inline uint8_t slow_index_convert_w(HashTable *ht, const zval
value->lval = 1;
return IS_LONG;
default:
zend_illegal_array_offset(dim);
zend_illegal_array_offset_access(dim);
return IS_NULL;
}
}
Expand Down Expand Up @@ -2762,7 +2762,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
ZVAL_NULL(result);
return;
}
zend_illegal_string_offset(dim);
zend_illegal_string_offset(dim, BP_VAR_R);
ZVAL_NULL(result);
return;
}
Expand Down Expand Up @@ -2801,7 +2801,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
dim = Z_REFVAL_P(dim);
goto try_string_offset;
default:
zend_illegal_string_offset(dim);
zend_illegal_string_offset(dim, BP_VAR_R);
ZVAL_NULL(result);
return;
}
Expand Down Expand Up @@ -2923,7 +2923,7 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable
ZVAL_UNDEFINED_OP2();
goto str_idx;
} else {
zend_illegal_empty_or_isset_offset(offset);
zend_illegal_array_offset_isset(offset);
return NULL;
}
}
Expand Down Expand Up @@ -3046,7 +3046,7 @@ static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable
str = ZSTR_EMPTY_ALLOC();
goto str_key;
} else {
zend_illegal_array_offset(key);
zend_illegal_array_offset_access(key);
return 0;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -6098,7 +6098,7 @@ ZEND_VM_C_LABEL(num_index):
str = ZSTR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index);
} else {
zend_illegal_array_offset(offset);
zend_illegal_array_offset_access(offset);
zval_ptr_dtor_nogc(expr_ptr);
}
FREE_OP2();
Expand Down Expand Up @@ -6610,7 +6610,7 @@ ZEND_VM_C_LABEL(num_index_dim):
key = ZSTR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index_dim);
} else {
zend_illegal_unset_offset(offset);
zend_illegal_array_offset_unset(offset);
}
break;
} else if (Z_ISREF_P(container)) {
Expand Down
Loading