[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exceeding memory limit in zend_hash_do_resize leaves the array in an invalid state #11189

Closed
bwoebi opened this issue May 5, 2023 · 0 comments · Fixed by ThePHPF/thephp.foundation#90

Comments

@bwoebi
Copy link
Member
bwoebi commented May 5, 2023

Description

Cross-posting a report we got on our extension: DataDog/dd-trace-php#2030 (comment)

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:

php-src/Zend/zend_hash.c

Lines 1250 to 1251 in a65cdd9

ht->nTableSize = nSize;
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants
@bwoebi and others