Heap buffer overflow in array_merge()

Inhalt

The following PHP code triggers a reliable heap buffer overflow:

$arr = range(0, 2**29);
array_merge($arr, $arr, $arr, $arr, $arr, $arr, $arr, $arr);

Or the general case:

$power = 24; // You can choose this number 1 <= $power < 32
$arr = range(0, 2**$power);
array_merge(...array_fill(0, 2**(32-$power), $arr));

This is because packed arrays in array_merge() have an optimization that requires precomputing the count of the elements, done using count += zend_hash_num_elements(Z_ARRVAL_P(arg));. However, this may overflow. Note that even if it didn't, it would cause a DoS because array_init() will trigger a bailout with too large counts.

The code provided is artificial, but I believe this can happen in the real world with for example large sets of JSON data that are then passed to array_merge(). The total count just has to exceed HT_MAX_SIZE to trigger the DoS or the 32-bit limit to trigger the buffer overflow.

Impact

If we were using a memory safe language we would "just" be limited to the DoS, but now we have heap corruption and all the joys of it. This bug has been in PHP since PHP 7.1.

Workarounds

Prevent a large number of inputs of long arrays to array_merge().

Security impact

As noted the example code is just a PoC exploit trigger.

The JSON file could be crafted and loaded via json_decode that results in a structure like: [array1, array2, array3, ...]. Then the code could use array_merge(array1, array2, array3, ...) from the JSON data. The arrays itself may be relatively small but if the sum of elements exceed the HT_MAX_SIZE bound, the buffer overflow is triggered.

Something like this:

Verknuepfte CVEs

CVE-ID Severity (CVE.org) CVSS (CVE.org) EPSS EPSS-% Veroeffentlicht (CVE.org)

CVE-2025-14178

- - - -

Quellen-Details

Bezeichnung Name Kategorie Tags Zielgruppe Sprache Feed-URL
PHP Security (php/php-src GHSA)

php_sec

vendor_advisory php, runtime - de https://github.com/php/php-src/security/advisories