Description
Random\Engine\Mt19937::__debugInfo() allocates a temporary HashTable with array_init(&t) and then calls engine->engine.algo->serialize(). If the callback returns false, the method throws "Engine serialize failed" and returns via RETURN_THROWS() before t gets inserted anywhere, so the HashTable leaks. PcgOneseq128XslRr64::__debugInfo() and Xoshiro256StarStar::__debugInfo() alias the same implementation and inherit the same leak.
Niels Dossche fixed this exact pattern in __serialize() in #20383 (720e006, "random: Fix memory leak when serialization fails"). That cleanup didn't touch __debugInfo().
The path is latent in stock PHP because the three built-in serialize callbacks (mt19937, pcg, xoshiro) all return true, so no user code can reach the leak today. I'm filing it anyway for symmetry with the #20383 fix and to keep the pattern from regressing if a future engine's serialize grows a failure mode.
Reproduction
Force the latent path with a one-line patch:
--- a/ext/random/engine_mt19937.c
+++ b/ext/random/engine_mt19937.c
@@ -174,6 +174,7 @@ static bool serialize(void *state, HashTable *data)
{
php_random_status_state_mt19937 *s = state;
zval t;
+ return false;
Run:
<?php
(new Random\Engine\Mt19937(1234))->__debugInfo();
under valgrind:
USE_ZEND_ALLOC=0 valgrind --leak-check=full --show-leak-kinds=definite \
sapi/cli/php repro.php
Output:
==3067603== 56 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3067603== at 0x4848899: malloc
==3067603== by 0x70B5CC: __zend_malloc (zend_alloc.c:3544)
==3067603== by 0x7B011C: _zend_new_array_0 (zend_hash.c:283)
==3067603== by 0x59AAB4: zim_Random_Engine_Mt19937___debugInfo (engine_mt19937.c:396)
PHP Version
master (PHP 8.6.0-dev). The block hasn't changed in 8.3/8.4/8.5 either, so all supported branches carry the same latent leak.
Description
Random\Engine\Mt19937::__debugInfo()allocates a temporaryHashTablewitharray_init(&t)and then callsengine->engine.algo->serialize(). If the callback returnsfalse, the method throws "Engine serialize failed" and returns viaRETURN_THROWS()beforetgets inserted anywhere, so the HashTable leaks.PcgOneseq128XslRr64::__debugInfo()andXoshiro256StarStar::__debugInfo()alias the same implementation and inherit the same leak.Niels Dossche fixed this exact pattern in
__serialize()in #20383 (720e006, "random: Fix memory leak when serialization fails"). That cleanup didn't touch__debugInfo().The path is latent in stock PHP because the three built-in
serializecallbacks (mt19937, pcg, xoshiro) all returntrue, so no user code can reach the leak today. I'm filing it anyway for symmetry with the #20383 fix and to keep the pattern from regressing if a future engine'sserializegrows a failure mode.Reproduction
Force the latent path with a one-line patch:
Run:
under valgrind:
Output:
PHP Version
master (PHP 8.6.0-dev). The block hasn't changed in 8.3/8.4/8.5 either, so all supported branches carry the same latent leak.