|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-06-17 16:42 UTC] james dot h dot cracknell at gmail dot com
Description: ------------ Note the following in the provided stack trace: struct real_pcre * argument_re = 0x00000001 I believe what is occurring here is if you use `preg_replace_callback` with a callback making (very) extensive use of PCRE functions, the outer regular expression gets evicted from the PCRE cache and freed before `preg_replace_callback` completes. Looking at `pcre_get_compiled_regex_cache`, it looks as though no checks are performed to prevent this from happening: https://github.com/php/php-src/blob/php-7.0.0alpha1/ext/pcre/php_pcre.c#L446 Switching to an approach using `preg_match_all` with manual replacement obviously sidesteps the issue. Stack trace follows, less the subject string value: php7!php_pcre_exec(struct real_pcre * argument_re = 0x00000001, struct pcre_extra * extra_data = 0x0d6074b8, char * subject = 0x0598fa10 "(snip)", int length = 0n1235, int start_offset = 0n997, int options = 0n8192, int * offsets = 0x052ac3f0, int offsetcount = 0n21)+0x149 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\pcrelib\pcre_exec.c @ 6420] php7!php_pcre_replace_impl(struct pcre_cache_entry * pce = 0x00ee58d8, struct _zend_string * subject_str = 0x0598fa00, char * subject = 0x0598fa10 "(snip)", int subject_len = 0n1235, struct _zval_struct * replace_val = 0x008143d0, int is_callable_replace = 0n1, int limit = 0n-1, int * replace_count = 0x052ac534)+0x148 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\php_pcre.c @ 1120] php7!php_pcre_replace+0x33 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\php_pcre.c @ 1026] php7!php_replace_in_subject(struct _zval_struct * regex = 0x008143c0, struct _zval_struct * replace = 0x008143d0, struct _zval_struct * subject = 0x008143e0, int limit = 0n-1, int is_callable_replace = 0n1, int * replace_count = 0x052ac534)+0x258 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\php_pcre.c @ 1353] php7!preg_replace_impl(struct _zval_struct * return_value = 0x00814370, struct _zval_struct * regex = 0x008143c0, struct _zval_struct * replace = 0x008143d0, struct _zval_struct * subject = 0x008143e0, int limit_val = 0n-1, int is_callable_replace = 0n1, int is_filter = 0n0)+0x264 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\php_pcre.c @ 1411] php7!zif_preg_replace_callback(struct _zend_execute_data * execute_data = <Value unavailable error>, struct _zval_struct * return_value = 0x00814370)+0x173 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\ext\pcre\php_pcre.c @ 1494] php7!ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER+0x2e6e14 [c:\php-sdk\php70dev\vc14\x86\php-7.0.0alpha1\zend\zend_vm_execute.h @ 701] Patchespcre-refcount (last revision 2015-06-18 12:49 UTC by cmb@php.net)quick-hack (last revision 2015-06-17 22:03 UTC by cmb@php.net) Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 09:00:01 2025 UTC |
This will crash on Windows and Linux: preg_replace_callback('/a/', function($m) { for($i = 0; $i < 10000; $i++) preg_replace('/foo'.$i.'bar/', 'baz', '???foo'.$i.'bar???'); return 'b'; }, 'aa');Thanks for further investigation, Anatol, and the valuable hints. Indeed, the valgrind issues are not (directly) related to the patch. The following test script raises lots of these for current master (w/o the patch): <?php for ($i = 0; $i < 10000; $i++) { preg_replace('/foo'.$i.'bar/', 'baz', '???foo'.$i.'bar???'); } ?> All this depends on pcre.jit. If this (php.ini) configuration option is disabled, valgrind reports no problems. Also James' test script runs fine with the patch if pcre.jit is disabled. It seems to me that the valgrind/pcre.jit issue is not directly related to this ticket, and that it might be best to open a new ticket for it. I think it would be preferable to solve that issue before finally tackling this ticket. Anyhow, disregard my comments regarding storing PCE vs. zval in the HashTable. I had not read the code carefully enough.