Browse Source

Fixed bug #22463 and bug #23581

migration/unlabaled-1.3.2
Moriyoshi Koizumi 24 years ago
parent
commit
4e9e9c6e21
  1. 84
      ext/standard/array.c

84
ext/standard/array.c

@ -3327,7 +3327,8 @@ PHP_FUNCTION(array_reduce)
zval *retval;
char *callback_name;
HashPosition pos;
HashTable *htbl;
if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 ||
zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &callback, &initial) == FAILURE) {
WRONG_PARAM_COUNT;
@ -3350,7 +3351,13 @@ PHP_FUNCTION(array_reduce)
zval_add_ref(&result);
}
if (zend_hash_num_elements(Z_ARRVAL_PP(input)) == 0) {
/* (zval **)input points to an element of argument stack
* the base pointer of which is subject to change.
* thus we need to keep the pointer to the hashtable for safety */
htbl = Z_ARRVAL_PP(input);
if (zend_hash_num_elements(htbl) == 0) {
if (result) {
*return_value = *result;
zval_copy_ctor(return_value);
@ -3358,8 +3365,8 @@ PHP_FUNCTION(array_reduce)
return;
}
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&operand, &pos) == SUCCESS) {
zend_hash_internal_pointer_reset_ex(htbl, &pos);
while (zend_hash_get_current_data_ex(htbl, (void **)&operand, &pos) == SUCCESS) {
if (result) {
args[0] = &result;
args[1] = operand;
@ -3375,7 +3382,7 @@ PHP_FUNCTION(array_reduce)
zval_add_ref(&result);
}
zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos);
zend_hash_move_forward_ex(htbl, &pos);
}
*return_value = *result;
@ -3463,11 +3470,12 @@ PHP_FUNCTION(array_filter)
Applies the callback to the elements in given arrays. */
PHP_FUNCTION(array_map)
{
zval ***args = NULL;
zval ***pargs = NULL;
zval ***params;
zval *callback;
zval *result, *null;
HashPosition *array_pos;
zval **args;
char *callback_name;
int i, k, maxlen = 0;
int *array_len;
@ -3476,47 +3484,52 @@ PHP_FUNCTION(array_map)
WRONG_PARAM_COUNT;
}
args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **));
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
efree(args);
RETVAL_NULL();
pargs = (zval ***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0);
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), pargs) == FAILURE) {
efree(pargs);
WRONG_PARAM_COUNT;
}
RETVAL_NULL();
callback = *pargs[0];
callback = *args[0];
if (Z_TYPE_P(callback) != IS_NULL) {
if (!zend_is_callable(callback, 0, &callback_name)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument, '%s', should be either NULL or a valid callback", callback_name);
efree(callback_name);
efree(args);
efree(pargs);
return;
}
efree(callback_name);
}
/* Allocate array sizes and iterators. */
array_len = (int*)emalloc((ZEND_NUM_ARGS()-1) * sizeof(int));
array_pos = (HashPosition*)emalloc((ZEND_NUM_ARGS()-1) * sizeof(HashPosition));
args = (zval **)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval *), 0);
array_len = (int *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(int), 0);
array_pos = (HashPosition *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(HashPosition), 0);
/* Check that arrays are indeed arrays and calculate maximum size. */
for (i = 0; i < ZEND_NUM_ARGS()-1; i++) {
if (Z_TYPE_PP(args[i+1]) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 2);
for (i = 1; i < ZEND_NUM_ARGS(); i++) {
if (Z_TYPE_PP(pargs[i]) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 1);
efree(pargs);
efree(args);
efree(array_len);
efree(array_pos);
efree(args);
return;
}
array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(args[i+1]));
if (array_len[i] > maxlen)
args[i] = *pargs[i];
array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(pargs[i]));
if (array_len[i] > maxlen) {
maxlen = array_len[i];
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args[i+1]), &array_pos[i]);
}
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(pargs[i]), &array_pos[i]);
}
efree(pargs);
/* Short-circuit: if no callback and only one array, just return it. */
if (Z_TYPE_P(callback) == IS_NULL && ZEND_NUM_ARGS() == 2) {
*return_value = **args[1];
*return_value = *args[1];
zval_copy_ctor(return_value);
efree(array_len);
efree(array_pos);
@ -3525,7 +3538,7 @@ PHP_FUNCTION(array_map)
}
array_init(return_value);
params = (zval ***)emalloc((ZEND_NUM_ARGS()-1) * sizeof(zval **));
params = (zval ***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0);
MAKE_STD_ZVAL(null);
ZVAL_NULL(null);
@ -3545,35 +3558,35 @@ PHP_FUNCTION(array_map)
array_init(result);
}
for (i = 0; i < ZEND_NUM_ARGS()-1; i++) {
for (i = 1; i < ZEND_NUM_ARGS(); i++) {
/*
* If this array still hash elements, add the current one to the
* parameter list, otherwise use null value.
*/
if (k < array_len[i]) {
zend_hash_get_current_data_ex(Z_ARRVAL_PP(args[i+1]), (void **)&params[i], &array_pos[i]);
zend_hash_get_current_data_ex(Z_ARRVAL_P(args[i]), (void **)&params[i], &array_pos[i]);
/*
* It is safe to store only last value of key type, because
* this loop will run just once if there is only 1 array.
*/
if (ZEND_NUM_ARGS() == 2) {
key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(args[1]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]);
key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(args[1]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]);
}
zend_hash_move_forward_ex(Z_ARRVAL_PP(args[i+1]), &array_pos[i]);
zend_hash_move_forward_ex(Z_ARRVAL_P(args[i]), &array_pos[i]);
} else {
if (Z_TYPE_P(callback) == IS_NULL)
zval_add_ref(&null);
params[i] = &null;
}
if (Z_TYPE_P(callback) == IS_NULL)
if (Z_TYPE_P(callback) == IS_NULL) {
zval_add_ref(params[i]);
add_next_index_zval(result, *params[i]);
}
}
if (Z_TYPE_P(callback) != IS_NULL) {
if (!call_user_function_ex(EG(function_table), NULL, callback, &result, ZEND_NUM_ARGS()-1, params, 0, NULL TSRMLS_CC) == SUCCESS && result) {
if (!call_user_function_ex(EG(function_table), NULL, callback, &result, ZEND_NUM_ARGS() - 1, &params[1], 0, NULL TSRMLS_CC) == SUCCESS && result) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the map callback");
efree(array_len);
efree(args);
@ -3586,10 +3599,11 @@ PHP_FUNCTION(array_map)
if (ZEND_NUM_ARGS() > 2) {
add_next_index_zval(return_value, result);
} else {
if (key_type == HASH_KEY_IS_STRING)
if (key_type == HASH_KEY_IS_STRING) {
add_assoc_zval_ex(return_value, str_key, str_key_len, result);
else
} else {
add_index_zval(return_value, num_key, result);
}
}
}

Loading…
Cancel
Save