diff options
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r-- | ext/standard/array.c | 479 |
1 files changed, 245 insertions, 234 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index d44e5d50e7..413ed319d7 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | @@ -365,7 +363,6 @@ static int php_array_data_compare(const void *a, const void *b) /* {{{ */ { Bucket *f; Bucket *s; - zval result; zval *first; zval *second; @@ -381,12 +378,7 @@ static int php_array_data_compare(const void *a, const void *b) /* {{{ */ if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) { second = Z_INDIRECT_P(second); } - if (compare_function(&result, first, second) == FAILURE) { - return 0; - } - - ZEND_ASSERT(Z_TYPE(result) == IS_LONG); - return ZEND_NORMALIZE_BOOL(Z_LVAL(result)); + return zend_compare(first, second); } /* }}} */ @@ -696,13 +688,12 @@ PHP_FUNCTION(krsort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_key_compare_func(sort_type, 1); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + RETURN_TRUE; } /* }}} */ @@ -719,13 +710,12 @@ PHP_FUNCTION(ksort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_key_compare_func(sort_type, 0); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + RETURN_TRUE; } /* }}} */ @@ -791,7 +781,7 @@ PHP_FUNCTION(count) /* first, we check if the handler is defined */ if (Z_OBJ_HT_P(array)->count_elements) { RETVAL_LONG(1); - if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value))) { + if (SUCCESS == Z_OBJ_HT(*array)->count_elements(Z_OBJ_P(array), &Z_LVAL_P(return_value))) { return; } if (EG(exception)) { @@ -800,7 +790,7 @@ PHP_FUNCTION(count) } /* if not and the object implements Countable we call its count() method */ if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) { - zend_call_method_with_0_params(array, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(Z_OBJ_P(array), NULL, NULL, "count", &retval); if (Z_TYPE(retval) != IS_UNDEF) { RETVAL_LONG(zval_get_long(&retval)); zval_ptr_dtor(&retval); @@ -830,13 +820,9 @@ static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */ ZEND_PARSE_PARAMETERS_END(); if (fold_case) { - if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0) == FAILURE) { - return; - } + zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0); } else { - if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0) == FAILURE) { - return; - } + zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0); } RETURN_TRUE; @@ -871,13 +857,12 @@ PHP_FUNCTION(asort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_data_compare_func(sort_type, 0); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + RETURN_TRUE; } /* }}} */ @@ -894,13 +879,12 @@ PHP_FUNCTION(arsort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_data_compare_func(sort_type, 1); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + RETURN_TRUE; } /* }}} */ @@ -917,13 +901,12 @@ PHP_FUNCTION(sort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_data_compare_func(sort_type, 0); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 1); + RETURN_TRUE; } /* }}} */ @@ -940,13 +923,12 @@ PHP_FUNCTION(rsort) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); cmp = php_get_data_compare_func(sort_type, 1); - if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) { - RETURN_FALSE; - } + zend_hash_sort(Z_ARRVAL_P(array), cmp, 1); + RETURN_TRUE; } /* }}} */ @@ -1016,7 +998,6 @@ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func, { zval *array; zend_array *arr; - zend_bool retval; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); @@ -1035,13 +1016,13 @@ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func, /* Copy array, so the in-place modifications will not be visible to the callback function */ arr = zend_array_dup(arr); - retval = zend_hash_sort(arr, compare_func, renumber) != FAILURE; + zend_hash_sort(arr, compare_func, renumber); zval_ptr_dtor(array); ZVAL_ARR(array, arr); PHP_ARRAY_CMP_FUNC_RESTORE(); - RETURN_BOOL(retval); + RETURN_TRUE; } /* }}} */ @@ -1254,7 +1235,9 @@ PHP_FUNCTION(key) } /* }}} */ -/* {{{ proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]]) +/* {{{ + * proto mixed min(array values) + * proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]]) Return the lowest value in an array or a series of arguments */ PHP_FUNCTION(min) { @@ -1270,14 +1253,14 @@ PHP_FUNCTION(min) zval *result; if (Z_TYPE(args[0]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array"); - RETVAL_NULL(); + zend_type_error("When only one parameter is given, it must be an array"); + return; } else { if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 0)) != NULL) { ZVAL_COPY_DEREF(return_value, result); } else { - php_error_docref(NULL, E_WARNING, "Array must contain at least one element"); - RETVAL_FALSE; + zend_throw_error(NULL, "Array must contain at least one element"); + return; } } } else { @@ -1299,7 +1282,9 @@ PHP_FUNCTION(min) } /* }}} */ -/* {{{ proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]]) +/* {{{ + * proto mixed max(array values) + * proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]]) Return the highest value in an array or a series of arguments */ PHP_FUNCTION(max) { @@ -1315,14 +1300,14 @@ PHP_FUNCTION(max) zval *result; if (Z_TYPE(args[0]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array"); - RETVAL_NULL(); + zend_type_error("When only one parameter is given, it must be an array"); + return; } else { if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 1)) != NULL) { ZVAL_COPY_DEREF(return_value, result); } else { - php_error_docref(NULL, E_WARNING, "Array must contain at least one element"); - RETVAL_FALSE; + zend_throw_error(NULL, "Array must contain at least one element"); + return; } } } else { @@ -1409,7 +1394,7 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */ SEPARATE_ARRAY(zv); thash = Z_ARRVAL_P(zv); if (GC_IS_RECURSIVE(thash)) { - php_error_docref(NULL, E_WARNING, "recursion detected"); + zend_throw_error(NULL, "Recursion detected"); result = FAILURE; break; } @@ -1460,7 +1445,7 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */ target_hash = Z_OBJPROP_P(array); pos = zend_hash_iterator_pos(ht_iter, target_hash); } else { - php_error_docref(NULL, E_WARNING, "Iterated value is no longer an array or object"); + zend_type_error("Iterated value is no longer an array or object"); result = FAILURE; break; } @@ -1716,16 +1701,16 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va } /* }}} */ -PHPAPI int php_prefix_varname(zval *result, const zval *prefix, const char *var_name, size_t var_name_len, zend_bool add_underscore) /* {{{ */ +PHPAPI int php_prefix_varname(zval *result, zend_string *prefix, const char *var_name, size_t var_name_len, zend_bool add_underscore) /* {{{ */ { - ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0)); - memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix)); + ZVAL_NEW_STR(result, zend_string_alloc(ZSTR_LEN(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0)); + memcpy(Z_STRVAL_P(result), ZSTR_VAL(prefix), ZSTR_LEN(prefix)); if (add_underscore) { - Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_'; + Z_STRVAL_P(result)[ZSTR_LEN(prefix)] = '_'; } - memcpy(Z_STRVAL_P(result) + Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1); + memcpy(Z_STRVAL_P(result) + ZSTR_LEN(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1); return SUCCESS; } @@ -1904,7 +1889,7 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table } /* }}} */ -static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -1960,7 +1945,7 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s } /* }}} */ -static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2011,7 +1996,7 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo } /* }}} */ -static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2085,7 +2070,7 @@ prefix: } /* }}} */ -static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2151,7 +2136,7 @@ prefix: } /* }}} */ -static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2198,7 +2183,7 @@ static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_ } /* }}} */ -static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2245,7 +2230,7 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl } /* }}} */ -static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2300,7 +2285,7 @@ static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *sym } /* }}} */ -static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */ +static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zend_string *prefix) /* {{{ */ { zend_long count = 0; zend_string *var_name; @@ -2441,9 +2426,10 @@ static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { - zval *var_array_param, *prefix = NULL; + zval *var_array_param; zend_long extract_refs; zend_long extract_type = EXTR_OVERWRITE; + zend_string *prefix = NULL; zend_long count; zend_array *symbol_table; @@ -2451,7 +2437,7 @@ PHP_FUNCTION(extract) Z_PARAM_ARRAY_EX2(var_array_param, 0, 1, 0) Z_PARAM_OPTIONAL Z_PARAM_LONG(extract_type) - Z_PARAM_ZVAL(prefix) + Z_PARAM_STR(prefix) ZEND_PARSE_PARAMETERS_END(); extract_refs = (extract_type & EXTR_REFS); @@ -2461,22 +2447,18 @@ PHP_FUNCTION(extract) extract_type &= 0xff; if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) { - php_error_docref(NULL, E_WARNING, "Invalid extract type"); + zend_throw_error(NULL, "Invalid extract type"); return; } if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) { - php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter"); + zend_throw_error(NULL, "Specified extract type requires the prefix parameter"); return; } if (prefix) { - if (!try_convert_to_string(prefix)) { - return; - } - - if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) { - php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier"); + if (ZSTR_LEN(prefix) && !php_valid_var_name(ZSTR_VAL(prefix), ZSTR_LEN(prefix))) { + zend_throw_error(NULL, "Prefix is not a valid identifier"); return; } } @@ -2486,6 +2468,7 @@ PHP_FUNCTION(extract) } symbol_table = zend_rebuild_symbol_table(); + ZEND_ASSERT(symbol_table && "A symbol table should always be available here"); if (extract_refs) { switch (extract_type) { @@ -2568,7 +2551,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu } else if (Z_TYPE_P(entry) == IS_ARRAY) { if (Z_REFCOUNTED_P(entry)) { if (Z_IS_RECURSIVE_P(entry)) { - php_error_docref(NULL, E_WARNING, "recursion detected"); + zend_throw_error(NULL, "Recursion detected"); return; } Z_PROTECT_RECURSION_P(entry); @@ -2600,9 +2583,7 @@ PHP_FUNCTION(compact) } symbol_table = zend_rebuild_symbol_table(); - if (UNEXPECTED(symbol_table == NULL)) { - return; - } + ZEND_ASSERT(symbol_table && "A symbol table should always be available here"); /* compact() is probably most used with a single array of var_names or multiple string names, rather than a combination of both. @@ -2634,11 +2615,11 @@ PHP_FUNCTION(array_fill) if (EXPECTED(num > 0)) { if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) { - php_error_docref(NULL, E_WARNING, "Too many elements"); - RETURN_FALSE; + zend_throw_error(NULL, "Too many elements"); + return; } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) { - php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied"); - RETURN_FALSE; + zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); + return; } else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) { /* create packed array */ Bucket *p; @@ -2683,8 +2664,8 @@ PHP_FUNCTION(array_fill) } else if (EXPECTED(num == 0)) { RETURN_EMPTY_ARRAY(); } else { - php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); - RETURN_FALSE; + zend_throw_error(NULL, "Number of elements can't be negative"); + return; } } /* }}} */ @@ -2721,8 +2702,9 @@ PHP_FUNCTION(array_fill_keys) #define RANGE_CHECK_DOUBLE_INIT_ARRAY(start, end) do { \ double __calc_size = ((start - end) / step) + 1; \ if (__calc_size >= (double)HT_MAX_SIZE) { \ - php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \ - RETURN_FALSE; \ + zend_throw_error(NULL, \ + "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \ + return; \ } \ size = (uint32_t)_php_math_round(__calc_size, 0, PHP_ROUND_HALF_UP); \ array_init_size(return_value, size); \ @@ -2732,8 +2714,9 @@ PHP_FUNCTION(array_fill_keys) #define RANGE_CHECK_LONG_INIT_ARRAY(start, end) do { \ zend_ulong __calc_size = ((zend_ulong) start - end) / lstep; \ if (__calc_size >= HT_MAX_SIZE - 1) { \ - php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=" ZEND_LONG_FMT " end=" ZEND_LONG_FMT, end, start); \ - RETURN_FALSE; \ + zend_throw_error(NULL, \ + "The supplied range exceeds the maximum array size: start=" ZEND_LONG_FMT " end=" ZEND_LONG_FMT, end, start); \ + return; \ } \ size = (uint32_t)(__calc_size + 1); \ array_init_size(return_value, size); \ @@ -2752,24 +2735,11 @@ PHP_FUNCTION(range) Z_PARAM_ZVAL(zlow) Z_PARAM_ZVAL(zhigh) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(zstep) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + Z_PARAM_NUMBER(zstep) + ZEND_PARSE_PARAMETERS_END(); if (zstep) { - if (Z_TYPE_P(zstep) == IS_DOUBLE) { - is_step_double = 1; - } else if (Z_TYPE_P(zstep) == IS_STRING) { - int type = is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0); - if (type == IS_DOUBLE) { - is_step_double = 1; - } - if (type == 0) { - /* bad number */ - php_error_docref(NULL, E_WARNING, "Invalid range string - must be numeric"); - RETURN_FALSE; - } - } - + is_step_double = Z_TYPE_P(zstep) == IS_DOUBLE; step = zval_get_double(zstep); /* We only want positive step values. */ @@ -2842,8 +2812,8 @@ double_str: high = zval_get_double(zhigh); if (zend_isinf(high) || zend_isinf(low)) { - php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high); - RETURN_FALSE; + zend_throw_error(NULL, "Invalid range supplied: start=%0.0f end=%0.0f", low, high); + return; } if (low > high) { /* Negative steps */ @@ -2935,8 +2905,8 @@ long_str: } err: if (err) { - php_error_docref(NULL, E_WARNING, "step exceeds the specified range"); - RETURN_FALSE; + zend_throw_error(NULL, "step exceeds the specified range"); + return; } } /* }}} */ @@ -3033,7 +3003,7 @@ PHP_FUNCTION(shuffle) ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_EX(array, 0, 1) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_END(); php_array_data_shuffle(array); @@ -3198,8 +3168,8 @@ PHP_FUNCTION(array_push) if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) { Z_TRY_DELREF(new_var); - php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied"); - RETURN_FALSE; + zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); + return; } } @@ -3243,7 +3213,7 @@ PHP_FUNCTION(array_pop) } ZVAL_COPY_DEREF(return_value, val); - if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { + if (!p->key && (zend_long)p->h == (Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; } @@ -3431,19 +3401,20 @@ PHP_FUNCTION(array_splice) HashTable *rem_hash = NULL; zend_long offset, length = 0; + zend_bool length_is_null = 1; int num_in; /* Number of elements in the input array */ ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL - Z_PARAM_LONG(length) + Z_PARAM_LONG_OR_NULL(length, length_is_null) Z_PARAM_ZVAL(repl_array) ZEND_PARSE_PARAMETERS_END(); num_in = zend_hash_num_elements(Z_ARRVAL_P(array)); - if (ZEND_NUM_ARGS() < 3) { + if (length_is_null) { length = num_in; } @@ -3474,6 +3445,9 @@ PHP_FUNCTION(array_splice) /* Initialize return value */ array_init_size(return_value, size > 0 ? (uint32_t)size : 0); rem_hash = Z_ARRVAL_P(return_value); + } else { + /* The return value will not be used, but make sure it still has the correct type. */ + RETVAL_EMPTY_ARRAY(); } /* Perform splice */ @@ -3481,18 +3455,44 @@ PHP_FUNCTION(array_splice) } /* }}} */ +/* {{{ find_bucket_at_offset(HashTable* ht, zend_long offset) + Finds the bucket at the given valid offset */ +static inline Bucket* find_bucket_at_offset(HashTable* ht, zend_long offset) +{ + zend_long pos; + Bucket *bucket; + ZEND_ASSERT(offset >= 0 && offset <= ht->nNumOfElements); + if (HT_IS_WITHOUT_HOLES(ht)) { + /* There's no need to iterate over the array to filter out holes if there are no holes */ + /* This properly handles both packed and unpacked arrays. */ + return ht->arData + offset; + } + /* Otherwise, this code has to iterate over the HashTable and skip holes in the array. */ + pos = 0; + ZEND_HASH_FOREACH_BUCKET(ht, bucket) { + if (pos >= offset) { + /* This is the bucket of the array element at the requested offset */ + return bucket; + } + ++pos; + } ZEND_HASH_FOREACH_END(); + + /* Return a pointer to the end of the bucket array. */ + return ht->arData + ht->nNumUsed; +} +/* }}} */ + /* {{{ proto array array_slice(array input, int offset [, int length [, bool preserve_keys]]) Returns elements specified by offset and length */ PHP_FUNCTION(array_slice) { - zval *input, /* Input array */ - *z_length = NULL, /* How many elements to get */ - *entry; /* An array entry */ - zend_long offset, /* Offset to get elements from */ - length = 0; - zend_bool preserve_keys = 0; /* Whether to preserve keys while copying to the new array or not */ - int num_in, /* Number of elements in the input array */ - pos; /* Current position in the array */ + zval *input; /* Input array */ + zval *entry; /* An array entry */ + zend_long offset; /* Offset to get elements from */ + zend_long length = 0; /* How many elements to get */ + zend_bool length_is_null = 1; /* Whether an explicit length has been omitted */ + zend_bool preserve_keys = 0; /* Whether to preserve keys while copying to the new array */ + uint32_t num_in; /* Number of elements in the input array */ zend_string *string_key; zend_ulong num_key; @@ -3500,7 +3500,7 @@ PHP_FUNCTION(array_slice) Z_PARAM_ARRAY(input) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(z_length) + Z_PARAM_LONG_OR_NULL(length, length_is_null) Z_PARAM_BOOL(preserve_keys) ZEND_PARSE_PARAMETERS_END(); @@ -3508,14 +3508,12 @@ PHP_FUNCTION(array_slice) num_in = zend_hash_num_elements(Z_ARRVAL_P(input)); /* We want all entries from offset to the end if length is not passed or is null */ - if (ZEND_NUM_ARGS() < 3 || Z_TYPE_P(z_length) == IS_NULL) { + if (length_is_null) { length = num_in; - } else { - length = zval_get_long(z_length); } /* Clamp the offset.. */ - if (offset > num_in) { + if (offset > (zend_long) num_in) { RETURN_EMPTY_ARRAY(); } else if (offset < 0 && (offset = (num_in + offset)) < 0) { offset = 0; @@ -3535,50 +3533,61 @@ PHP_FUNCTION(array_slice) /* Initialize returned array */ array_init_size(return_value, (uint32_t)length); - /* Start at the beginning and go until we hit offset */ - pos = 0; - if (HT_IS_PACKED(Z_ARRVAL_P(input)) && - (!preserve_keys || - (offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) { - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) { - pos++; - if (pos <= offset) { + // Contains modified variants of ZEND_HASH_FOREACH_VAL + { + HashTable *ht = Z_ARRVAL_P(input); + Bucket *p = find_bucket_at_offset(ht, offset); + Bucket *end = ht->arData + ht->nNumUsed; + + /* Start at the beginning and go until we hit offset */ + if (HT_IS_PACKED(Z_ARRVAL_P(input)) && + (!preserve_keys || + (offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) { + + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; p != end; p++) { + if (__fill_idx >= length) { + break; + } + entry = &p->val; + if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { + continue; + } + if (UNEXPECTED(Z_ISREF_P(entry)) && + UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { + entry = Z_REFVAL_P(entry); + } + Z_TRY_ADDREF_P(entry); + ZEND_HASH_FILL_ADD(entry); + } + } ZEND_HASH_FILL_END(); + } else { + zend_long n = 0; /* Current number of elements */ + for (; p != end; p++) { + entry = &p->val; + if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { continue; } - if (pos > offset + length) { + if (n >= length) { break; } - if (UNEXPECTED(Z_ISREF_P(entry)) && - UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { - entry = Z_REFVAL_P(entry); - } - Z_TRY_ADDREF_P(entry); - ZEND_HASH_FILL_ADD(entry); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); - } else { - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, string_key, entry) { - pos++; - if (pos <= offset) { - continue; - } - if (pos > offset + length) { - break; - } + n++; + num_key = p->h; + string_key = p->key; - if (string_key) { - entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry); - } else { - if (preserve_keys) { - entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry); + if (string_key) { + entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry); } else { - entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry); + if (preserve_keys) { + entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry); + } else { + entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry); + } } + zval_add_ref(entry); } - zval_add_ref(entry); - } ZEND_HASH_FOREACH_END(); + } } } /* }}} */ @@ -3601,7 +3610,7 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */ ZVAL_DEREF(dest_zval); thash = Z_TYPE_P(dest_zval) == IS_ARRAY ? Z_ARRVAL_P(dest_zval) : NULL; if ((thash && GC_IS_RECURSIVE(thash)) || (src_entry == dest_entry && Z_ISREF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) { - php_error_docref(NULL, E_WARNING, "recursion detected"); + zend_throw_error(NULL, "Recursion detected"); return 0; } @@ -3722,7 +3731,7 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ * if (Z_IS_RECURSIVE_P(dest_zval) || Z_IS_RECURSIVE_P(src_zval) || (Z_ISREF_P(src_entry) && Z_ISREF_P(dest_entry) && Z_REF_P(src_entry) == Z_REF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) { - php_error_docref(NULL, E_WARNING, "recursion detected"); + zend_throw_error(NULL, "Recursion detected"); return 0; } @@ -3771,8 +3780,8 @@ static zend_always_inline void php_array_replace_wrapper(INTERNAL_FUNCTION_PARAM zval *arg = args + i; if (Z_TYPE_P(arg) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg)); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg)); + return; } } @@ -3815,8 +3824,8 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET zval *arg = args + i; if (Z_TYPE_P(arg) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg)); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg)); + return; } count += zend_hash_num_elements(Z_ARRVAL_P(arg)); } @@ -3957,7 +3966,7 @@ PHP_FUNCTION(array_keys) /* Base case: empty input */ if (!elem_count) { - RETURN_ZVAL(input, 1, 0) + RETURN_ZVAL(input, 1, 0); } /* Initialize return array */ @@ -4016,7 +4025,7 @@ PHP_FUNCTION(array_keys) } /* }}} */ -/* {{{ proto mixed array_key_first(array stack) +/* {{{ proto int|string|false array_key_first(array stack) Get the key of the first element of the array */ PHP_FUNCTION(array_key_first) { @@ -4032,7 +4041,7 @@ PHP_FUNCTION(array_key_first) } /* }}} */ -/* {{{ proto mixed array_key_last(array stack) +/* {{{ proto int|string|false array_key_last(array stack) Get the key of the last element of the array */ PHP_FUNCTION(array_key_last) { @@ -4130,7 +4139,7 @@ PHP_FUNCTION(array_count_values) Z_LVAL_P(tmp)++; } } else { - php_error_docref(NULL, E_WARNING, "Can only count STRING and INTEGER values!"); + php_error_docref(NULL, E_WARNING, "Can only count string and integer values, entry skipped"); } } ZEND_HASH_FOREACH_END(); } @@ -4158,7 +4167,7 @@ zend_bool array_column_param_helper(zval *param, return 1; default: - php_error_docref(NULL, E_WARNING, "The %s key should be either a string or an integer", name); + zend_type_error("The %s key should be either a string or an integer", name); return 0; } } @@ -4172,9 +4181,12 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) /* /* The has_property check is first performed in "exists" mode (which returns true for * properties that are null but exist) and then in "has" mode to handle objects that * implement __isset (which is not called in "exists" mode). */ - if (Z_OBJ_HANDLER_P(data, has_property)(data, name, ZEND_PROPERTY_EXISTS, NULL) - || Z_OBJ_HANDLER_P(data, has_property)(data, name, ZEND_PROPERTY_ISSET, NULL)) { - prop = Z_OBJ_HANDLER_P(data, read_property)(data, name, BP_VAR_R, NULL, rv); + zend_string *str, *tmp_str; + + str = zval_get_tmp_string(name, &tmp_str); + if (Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), str, ZEND_PROPERTY_EXISTS, NULL) + || Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), str, ZEND_PROPERTY_ISSET, NULL)) { + prop = Z_OBJ_HANDLER_P(data, read_property)(Z_OBJ_P(data), str, BP_VAR_R, NULL, rv); if (prop) { ZVAL_DEREF(prop); if (prop != rv) { @@ -4182,6 +4194,7 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) /* } } } + zend_tmp_string_release(tmp_str); } else if (Z_TYPE_P(data) == IS_ARRAY) { if (Z_TYPE_P(name) == IS_STRING) { prop = zend_symtable_find(Z_ARRVAL_P(data), Z_STR_P(name)); @@ -4217,7 +4230,7 @@ PHP_FUNCTION(array_column) if ((column && !array_column_param_helper(column, "column")) || (index && !array_column_param_helper(index, "index"))) { - RETURN_FALSE; + return; } array_init_size(return_value, zend_hash_num_elements(input)); @@ -4372,8 +4385,8 @@ PHP_FUNCTION(array_pad) input_size = zend_hash_num_elements(Z_ARRVAL_P(input)); pad_size_abs = ZEND_ABS(pad_size); if (pad_size_abs < 0 || pad_size_abs - input_size > Z_L(1048576)) { - php_error_docref(NULL, E_WARNING, "You may only pad up to 1048576 elements at a time"); - RETURN_FALSE; + zend_throw_error(NULL, "You may only pad up to 1048576 elements at a time"); + return; } if (input_size >= pad_size_abs) { @@ -4469,7 +4482,7 @@ PHP_FUNCTION(array_flip) } zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } else { - php_error_docref(NULL, E_WARNING, "Can only flip STRING and INTEGER values!"); + php_error_docref(NULL, E_WARNING, "Can only flip string and integer values, entry skipped"); } } ZEND_HASH_FOREACH_END(); } @@ -4693,7 +4706,7 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa } if (argc < req_args) { - php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, argc); + zend_argument_count_error("At least %d parameters are required, %d given", req_args, argc); return; } @@ -4703,8 +4716,8 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa for (i = 0; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } } @@ -4788,12 +4801,12 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int param_spec = "+f"; intersect_data_compare_func = php_array_user_compare; } else { - php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type); + ZEND_ASSERT(0 && "Invalid data_compare_type"); return; } if (ZEND_NUM_ARGS() < req_args) { - php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + zend_argument_count_error("At least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); return; } @@ -4840,12 +4853,12 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int fci_key = &fci2; fci_key_cache = &fci2_cache; } else { - php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type); + ZEND_ASSERT(0 && "Invalid data_compare_type / key_compare_type"); return; } if (ZEND_NUM_ARGS() < req_args) { - php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + zend_argument_count_error("At least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); return; } @@ -4854,7 +4867,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int } } else { - php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior); + ZEND_ASSERT(0 && "Invalid behavior"); return; } @@ -4874,7 +4887,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int for (i = 0; i < arr_argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); arr_argc = i; /* only free up to i - 1 */ goto out; } @@ -5092,7 +5105,7 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty argc = ZEND_NUM_ARGS(); if (data_compare_type == DIFF_COMP_DATA_USER) { if (argc < 3) { - php_error_docref(NULL, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS()); + zend_argument_count_error("At least 3 parameters are required, %d given", ZEND_NUM_ARGS()); return; } if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { @@ -5101,7 +5114,7 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty diff_data_compare_func = zval_user_compare; } else { if (argc < 2) { - php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS()); + zend_argument_count_error("At least 2 parameters are required, %d given", ZEND_NUM_ARGS()); return; } if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { @@ -5114,8 +5127,8 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty for (i = 0; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } } @@ -5204,7 +5217,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ } if (ZEND_NUM_ARGS() < req_args) { - php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + zend_argument_count_error("At least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); return; } @@ -5251,12 +5264,12 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ fci_key = &fci2; fci_key_cache = &fci2_cache; } else { - php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type); + ZEND_ASSERT(0 && "Invalid data_compare_type / key_compare_type"); return; } if (ZEND_NUM_ARGS() < req_args) { - php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); + zend_argument_count_error("At least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS()); return; } @@ -5265,7 +5278,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ } } else { - php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior); + ZEND_ASSERT(0 && "Invalid behavior"); return; } @@ -5285,7 +5298,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ for (i = 0; i < arr_argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); arr_argc = i; /* only free up to i - 1 */ goto out; } @@ -5453,7 +5466,7 @@ PHP_FUNCTION(array_diff) zval dummy; if (ZEND_NUM_ARGS() < 2) { - php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS()); + zend_argument_count_error("At least 2 parameters are required, %d given", ZEND_NUM_ARGS()); return; } @@ -5462,16 +5475,16 @@ PHP_FUNCTION(array_diff) ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE(args[0]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0])); - RETURN_NULL(); + zend_type_error("Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0])); + return; } num = zend_hash_num_elements(Z_ARRVAL(args[0])); if (num == 0) { for (i = 1; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } } RETURN_EMPTY_ARRAY(); @@ -5487,8 +5500,8 @@ PHP_FUNCTION(array_diff) if (!value) { for (i = 1; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } } RETURN_EMPTY_ARRAY(); @@ -5498,8 +5511,8 @@ PHP_FUNCTION(array_diff) for (i = 1; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } if (!found) { ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) { @@ -5528,8 +5541,8 @@ PHP_FUNCTION(array_diff) num = 0; for (i = 1; i < argc; i++) { if (Z_TYPE(args[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); - RETURN_NULL(); + zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i])); + return; } num += zend_hash_num_elements(Z_ARRVAL(args[i])); } @@ -5636,7 +5649,7 @@ PHPAPI int php_multisort_compare(const void *a, const void *b) /* {{{ */ #define MULTISORT_ABORT \ efree(func); \ efree(arrays); \ - RETURN_FALSE; + return; static void array_bucket_p_sawp(void *p, void *q) /* {{{ */ { Bucket *t; @@ -5713,7 +5726,7 @@ PHP_FUNCTION(array_multisort) sort_order = Z_LVAL_P(arg) == PHP_SORT_DESC ? PHP_SORT_DESC : PHP_SORT_ASC; parse_state[MULTISORT_ORDER] = 0; } else { - php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1); + zend_type_error("Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1); MULTISORT_ABORT; } break; @@ -5729,19 +5742,19 @@ PHP_FUNCTION(array_multisort) sort_type = (int)Z_LVAL_P(arg); parse_state[MULTISORT_TYPE] = 0; } else { - php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1); + zend_type_error("Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1); MULTISORT_ABORT; } break; default: - php_error_docref(NULL, E_WARNING, "Argument #%d is an unknown sort flag", i + 1); + zend_type_error("Argument #%d is an unknown sort flag", i + 1); MULTISORT_ABORT; break; } } else { - php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or a sort flag", i + 1); + zend_type_error("Argument #%d is expected to be an array or a sort flag", i + 1); MULTISORT_ABORT; } } @@ -5752,7 +5765,7 @@ PHP_FUNCTION(array_multisort) array_size = zend_hash_num_elements(Z_ARRVAL_P(arrays[0])); for (i = 0; i < num_arrays; i++) { if (zend_hash_num_elements(Z_ARRVAL_P(arrays[i])) != (uint32_t)array_size) { - php_error_docref(NULL, E_WARNING, "Array sizes are inconsistent"); + zend_throw_error(NULL, "Array sizes are inconsistent"); MULTISORT_ABORT; } } @@ -5824,7 +5837,7 @@ PHP_FUNCTION(array_multisort) } /* }}} */ -/* {{{ proto mixed array_rand(array input [, int num_req]) +/* {{{ proto int|string|array array_rand(array input [, int num_req]) Return key/keys for random entry/entries in the array */ PHP_FUNCTION(array_rand) { @@ -5848,7 +5861,7 @@ PHP_FUNCTION(array_rand) num_avail = zend_hash_num_elements(Z_ARRVAL_P(input)); if (num_avail == 0) { - php_error_docref(NULL, E_WARNING, "Array is empty"); + zend_throw_error(NULL, "Array is empty"); return; } @@ -5889,7 +5902,7 @@ PHP_FUNCTION(array_rand) } if (num_req <= 0 || num_req > num_avail) { - php_error_docref(NULL, E_WARNING, "Second argument has to be between 1 and the number of elements in the array"); + zend_throw_error(NULL, "Second argument has to be between 1 and the number of elements in the array"); return; } @@ -5935,7 +5948,7 @@ PHP_FUNCTION(array_rand) } /* }}} */ -/* {{{ proto mixed array_sum(array input) +/* {{{ proto int|float array_sum(array input) Returns the sum of the array entries */ PHP_FUNCTION(array_sum) { @@ -5960,7 +5973,7 @@ PHP_FUNCTION(array_sum) } /* }}} */ -/* {{{ proto mixed array_product(array input) +/* {{{ proto int|float array_product(array input) Returns the product of the array entries */ PHP_FUNCTION(array_product) { @@ -6063,7 +6076,7 @@ PHP_FUNCTION(array_reduce) } /* }}} */ -/* {{{ proto array array_filter(array input [, mixed callback]) +/* {{{ proto array array_filter(array input [, mixed callback [, int use_type]]) Filters elements from the array via the callback. */ PHP_FUNCTION(array_filter) { @@ -6172,8 +6185,6 @@ PHP_FUNCTION(array_map) Z_PARAM_VARIADIC('+', arrays, n_arrays) ZEND_PARSE_PARAMETERS_END(); - RETVAL_NULL(); - if (n_arrays == 1) { zend_ulong num_key; zend_string *str_key; @@ -6181,7 +6192,7 @@ PHP_FUNCTION(array_map) int ret; if (Z_TYPE(arrays[0]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter 2 to be an array, %s given", zend_zval_type_name(&arrays[0])); + zend_type_error("Expected parameter 2 to be an array, %s given", zend_zval_type_name(&arrays[0])); return; } maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0])); @@ -6222,7 +6233,7 @@ PHP_FUNCTION(array_map) for (i = 0; i < n_arrays; i++) { if (Z_TYPE(arrays[i]) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 2, zend_zval_type_name(&arrays[i])); + zend_type_error("Expected parameter %d to be an array, %s given", i + 2, zend_zval_type_name(&arrays[i])); efree(array_pos); return; } @@ -6381,7 +6392,7 @@ PHP_FUNCTION(array_chunk) /* Do bounds checking for size parameter. */ if (size < 1) { - php_error_docref(NULL, E_WARNING, "Size parameter expected to be greater than 0"); + zend_throw_error(NULL, "Size parameter expected to be greater than 0"); return; } @@ -6446,8 +6457,8 @@ PHP_FUNCTION(array_combine) num_values = zend_hash_num_elements(values); if (num_keys != num_values) { - php_error_docref(NULL, E_WARNING, "Both parameters should have an equal number of elements"); - RETURN_FALSE; + zend_throw_error(NULL, "Both parameters should have an equal number of elements"); + return; } if (!num_keys) { |