[php-src] Issue #10240: HT_MAX_SIZE is to too large

From: Date: Fri, 06 Jan 2023 14:31:53 +0000
Subject: [php-src] Issue #10240: HT_MAX_SIZE is to too large
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-243359@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/10240 Author: arnaud-lb ### Description Found while testing https://github.com/php/php-src/pull/10149 The following code: ```php <?php $start_index = -1; // Force unpacked array array_fill($start_index, (2**30)+1, 0); ``` Resulted in this output: ``` php: /home/ubuntu/php-src/Zend/zend_hash.c:219: zend_hash_real_init_mixed_ex: Assertion `size >= 64 && ((size & 0x3f) == 0)' failed. ``` But I expected this output instead: ``` (no output) ``` gdb: ``` gdb $ gdb --args sapi/cli/php -d memory_limit=-1 test.php (gdb) r Starting program: /home/ubuntu/php-src/sapi/cli/php -d memory_limit=-1 test.php [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". php: /home/ubuntu/php-src/Zend/zend_hash.c:219: zend_hash_real_init_mixed_ex: Assertion `size >= 64 && ((size & 0x3f) == 0)' failed. Program received signal SIGABRT, Aborted. __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737339844544) at ./nptl/pthread_kill.c:44 44 ./nptl/pthread_kill.c: No such file or directory. (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737339844544) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=140737339844544) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=140737339844544, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x00007ffff72c5476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x00007ffff72ab7f3 in __GI_abort () at ./stdlib/abort.c:79 #5 0x00007ffff72ab71b in __assert_fail_base (fmt=0x7ffff7460150 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5555565fca80 "size >= 64 && ((size & 0x3f) == 0)", file=0x5555565fc980 "/home/ubuntu/php-src/Zend/zend_hash.c", line=219, function=<optimized out>) at ./assert/assert.c:92 #6 0x00007ffff72bce96 in __GI___assert_fail (assertion=0x5555565fca80 "size >= 64 && ((size & 0x3f) == 0)", file=0x5555565fc980 "/home/ubuntu/php-src/Zend/zend_hash.c", line=219, function=0x5555565fd320 <__PRETTY_FUNCTION__.49> "zend_hash_real_init_mixed_ex") at ./assert/assert.c:101 #7 0x0000555555ea6f58 in zend_hash_real_init_mixed_ex (ht=0x7ffff3c4b3c0) at /home/ubuntu/php-src/Zend/zend_hash.c:219 #8 0x0000555555ea8101 in zend_hash_real_init_mixed (ht=0x7ffff3c4b3c0) at /home/ubuntu/php-src/Zend/zend_hash.c:335 #9 0x0000555555b13652 in zif_array_fill (execute_data=0x7ffff3c060a0, return_value=0x7fffffffa1b0) at /home/ubuntu/php-src/ext/standard/array.c:2604 #10 0x0000555555f09cec in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER () at /home/ubuntu/php-src/Zend/zend_vm_execute.h:1235 #11 0x0000555556053dda in execute_ex (ex=0x7ffff3c06020) at /home/ubuntu/php-src/Zend/zend_vm_execute.h:55771 #12 0x0000555556066e18 in zend_execute (op_array=0x7ffff3c4f280, return_value=0x0) at /home/ubuntu/php-src/Zend/zend_vm_execute.h:60147 #13 0x0000555555e74a88 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/ubuntu/php-src/Zend/zend.c:1799 #14 0x0000555555d077e9 in php_execute_script (primary_file=0x7fffffffcdc0) at /home/ubuntu/php-src/main/main.c:2541 #15 0x0000555556240c1d in do_cli (argc=4, argv=0x604000000090) at /home/ubuntu/php-src/sapi/cli/php_cli.c:965 #16 0x0000555556242ed7 in main (argc=4, argv=0x604000000090) at /home/ubuntu/php-src/sapi/cli/php_cli.c:1367 (gdb) frame 7 #7 0x0000555555ea6f58 in zend_hash_real_init_mixed_ex (ht=0x7ffff3c4b3c0) at /home/ubuntu/php-src/Zend/zend_hash.c:219 219 HT_HASH_RESET(ht); (gdb) list 214 data = emalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize))); 215 } 216 ht->nTableMask = HT_SIZE_TO_MASK(nSize); 217 HT_SET_DATA_ADDR(ht, data); 218 HT_FLAGS(ht) = HASH_FLAG_STATIC_KEYS; 219 HT_HASH_RESET(ht); 220 } 221 222 static zend_always_inline void zend_hash_real_init_ex(HashTable *ht, bool packed) 223 { (gdb) p nSize $1 = 2147483648 (gdb) p nSize == 0x80000000 // HT_MAX_SIZE $2 = 1 (gdb) p ht->nTableMask $3 = 0 (gdb) p ((uint32_t)(-((nSize) + (nSize)))) // HT_SIZE_TO_MASK $4 = 0 ``` nSize is an uint32_t. HT_MAX_SIZE is 0x80000000 (2**31), so nSize+nSize HT_SIZE_TO_MASK overflows uint32_t, leading to ht->nTableMask == 0. ### PHP Version PHP 8.1 ### Operating System _No response_

« previous php.bugs (#243359) next »