[php-src] Issue #11189: Exceeding memory limit in zend_hash_do_resize leaves the array in an invalid state
| From: | bwoebi | Date: | Fri, 05 May 2023 09:57:42 +0000 |
| Subject: | [php-src] Issue #11189: Exceeding memory limit in zend_hash_do_resize leaves the array in an invalid state | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-244373@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/11189
Author: bwoebi
### Description
Cross-posting a report we got on our extension: https://github.com/DataDog/dd-trace-php/issues/2030#issuecomment-1535130277
```
php -dmemory_limit=10M -r 'ob_start(function() { global $a; for ($i = count($a); $i > 0;
--$i) { $a[] = 2; } }); $a = []; while (1) { $a[] = 1; }'
```
Getting a memory limit exceeded error in zend_hash_do_resize crashes when the array is manipulated
afterwards, with a following backtrace:
```
#0 _zend_hash_index_add_or_update_i (flag=18, pData=0xfffff4690150, h=262399, ht=0xfffff4655230) at
/usr/local/src/php/Zend/zend_hash.c:1051
#1 zend_hash_next_index_insert (ht=ht@entry=0xfffff4655230, pData=0xfffff4690150) at
/usr/local/src/php/Zend/zend_hash.c:1142
#2 0x0000aaaaaaf7c8bc in ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER () at
/usr/local/src/php/Zend/zend_vm_execute.h:47376
#3 0x0000aaaaaaf98558 in execute_ex (ex=0xfffff3c00ff8) at
/usr/local/src/php/Zend/zend_vm_execute.h:59995
#4 0x0000aaaaaaf17464 in zend_call_function (fci_cache=0xfffff4654120, fci=0xfffff46540e0) at
/usr/local/src/php/Zend/zend_execute_API.c:930
#5 zend_call_function (fci=0xfffff46540e0, fci_cache=<optimized out>) at
/usr/local/src/php/Zend/zend_execute_API.c:732
#6 0x0000aaaaaaf2f964 in zend_fcall_info_call (fci=0xfffff46540e0, fcc=0xfffff4654120,
retval_ptr=retval_ptr@entry=0xffffffffd218, args=args@entry=0x0) at
/usr/local/src/php/Zend/zend_API.c:4137
#7 0x0000aaaaaaed60f4 in php_output_handler_op (context=0xffffffffd248, handler=0xfffff466f050) at
/usr/local/src/php/main/output.c:970
#8 php_output_stack_pop (flags=flags@entry=17) at /usr/local/src/php/main/output.c:1231
#9 0x0000aaaaaaed6598 in php_output_discard_all () at /usr/local/src/php/main/output.c:365
#10 0x0000aaaaaabde368 in php_error_cb (orig_type=1, error_filename=0xfffff465b360, error_lineno=1,
message=0xfffff4654150) at /usr/local/src/php/main/main.c:1274
#11 0x0000aaaaaabdfbe8 in zend_error_zstr_at (orig_type=orig_type@entry=1,
error_filename=error_filename@entry=0xfffff465b360, error_lineno=error_lineno@entry=1,
message=message@entry=0xfffff4654150) at /usr/local/src/php/Zend/zend.c:1390
#12 0x0000aaaaaabdff48 in zend_error_va_list (orig_type=1, error_filename=0xfffff465b360,
error_lineno=1, format=<optimized out>, args=<error reading variable: Cannot access memory
at address 0x80000>) at /usr/local/src/php/Zend/zend.c:1483
#13 0x0000aaaaaabe02a0 in zend_error_noreturn (type=type@entry=1, format=format@entry=0xaaaaab87f740
"Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)") at
/usr/local/src/php/Zend/zend.c:1590
#14 0x0000aaaaaabdf594 in zend_mm_safe_error (format=format@entry=0xaaaaab87f740 "Allowed
memory size of %zu bytes exhausted (tried to allocate %zu bytes)", limit=10485760,
size=size@entry=8388616, heap=<optimized out>) at /usr/local/src/php/Zend/zend_alloc.c:383
#15 0x0000aaaaaaefb094 in zend_mm_realloc_huge (heap=0xfffff4600040, ptr=0xfffff3800000,
size=8388616, copy_size=4194312) at /usr/local/src/php/Zend/zend_alloc.c:1542
#16 0x0000aaaaaaf327b8 in zend_hash_packed_grow (ht=0xfffff4655230) at
/usr/local/src/php/Zend/zend_types.h:648
#17 0x0000aaaaaaf35490 in _zend_hash_index_add_or_update_i (flag=18, pData=0xfffff4693160, h=262144,
ht=0xfffff4655230) at /usr/local/src/php/Zend/zend_hash.c:1057
#18 zend_hash_next_index_insert (ht=ht@entry=0xfffff4655230, pData=0xfffff4693160) at
/usr/local/src/php/Zend/zend_hash.c:1142
#19 0x0000aaaaaaf7c8bc in ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER () at
/usr/local/src/php/Zend/zend_vm_execute.h:47376
#20 0x0000aaaaaaf98558 in execute_ex (ex=0xfffff3c00ff8) at
/usr/local/src/php/Zend/zend_vm_execute.h:59995
#21 0x0000aaaaaafa2648 in zend_execute (op_array=0xfffff467d100, return_value=0xffffffffd968) at
/usr/local/src/php/Zend/zend_vm_execute.h:60380
#22 0x0000aaaaaaf16aa8 in zend_eval_stringl (str=<optimized out>, str_len=<optimized
out>, retval_ptr=0x0, string_name=<optimized out>) at
/usr/local/src/php/Zend/zend_execute_API.c:1279
#23 0x0000aaaaaaf16c44 in zend_eval_stringl_ex (str=<optimized out>, str_len=<optimized
out>, retval_ptr=<optimized out>, string_name=<optimized out>,
handle_exceptions=true) at /usr/local/src/php/Zend/zend_execute_API.c:1321
#24 0x0000aaaaab0102f4 in do_cli (argc=4, argv=0xaaaaaba52870) at
/usr/local/src/php/sapi/cli/php_cli.c:995
#25 0x0000aaaaaabf76f8 in main (argc=4, argv=<optimized out>) at
/usr/local/src/php/sapi/cli/php_cli.c:1333
```
This happens due to the order of operations being the wrong way round in
zend_hash_do_resize:
https://github.com/php/php-src/blob/a65cdd97a148dccdb68a5f58c258d54c305f1b2e/Zend/zend_hash.c#L1250-L1251
It's setting the nTableSize before attempting to do the allocation, leaving the array in an
unstable state.
### PHP Version
PHP 8.1+
### Operating System
_No response_