Why does array_pad prevent to add at more than 1048576 elements at a time?

Viewed 236

The array_pad docs say that

It is possible to add at most 1048576 elements at a time.

I tried to find any information where the limit comes from and could not find any. The only somehow related question are about PDO: #1, #2 and the solution is to enlarge the size of the buffer. But there is no PDO in array_pad.

It is absolutely possible to create an array that contains more elements:

$array = range(1, 1048576 + 10);
echo count($array); // prints 1048586

And indeed, there is a hardcoded check not to exceed this value in the array_pad sources.

But... why?

1 Answers

Why range produce an array of more than 1048576 elements?

From PHP sources:

// ext/standard/array.c
PHP_FUNCTION(range)
{
   ...
   Z_PARAM_ZVAL(zlow)
   Z_PARAM_ZVAL(zhigh)
   Z_PARAM_OPTIONAL
   Z_PARAM_ZVAL(zstep)
   ...
   RANGE_CHECK_LONG_INIT_ARRAY(low, high);
   ...

RANGE_CHECK_LONG_INIT_ARRAY Macro checks if the size of the requested sequence doesn't exceed or equal the max size HT_MAX_SIZE - 1(HashTable Max Size)

// ext/standard/array.c
#define RANGE_CHECK_LONG_INIT_ARRAY(start, end) do { \
        zend_ulong __calc_size = (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; \
        } \

HT_MAX_SIZE value:

// Zend/types_types.h
#if SIZEOF_SIZE_T == 4 // 32 bit
# define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
...
#elif SIZEOF_SIZE_T == 8 // 64 bit
# define HT_MAX_SIZE 0x80000000

So we can see that the max size of the array that will be generated by rang() is: 0x04000000 - 2 = 67108862 on 32 bit systems and 0x80000000 - 2 = 2147483646 on 64 bit systems.

php > echo count(range(0,67108863));
PHP Warning:  range(): The supplied range exceeds the maximum array size: start=0 end=67108863 in php shell code on line 1


php > echo count(range(0,67108862));
PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 1610612744 bytes) in php shell code on line 1

Why does array_pad prevent to add more than 1048576 elements at a time?

From PHP sources:

// ext/standard/array.c
PHP_FUNCTION(array_pad)
{
    ...
    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;
     }

The value 1048576 is hard encoded.

Related