Sorry, I have accidentally committed without log. This is a MFB of the fix for #37911 which had been fixed in 5.3 but not in 5.2, fixes #45748.
On Friday 08 August 2008 11:34:08 Arnaud Le Blanc wrote: > lbarnaud Fri Aug 8 09:34:08 2008 UTC > > Added files: (Branch: PHP_5_2) > /php-src/ext/pcre/tests bug37911.phpt > > Modified files: > /php-src/ext/pcre php_pcre.c > Log: > > > http://cvs.php.net/viewvc.cgi/php-src/ext/pcre/php_pcre.c?r1=1.168.2.9.2.25 >&r2=1.168.2.9.2.26&diff_format=u Index: php-src/ext/pcre/php_pcre.c > diff -u php-src/ext/pcre/php_pcre.c:1.168.2.9.2.25 > php-src/ext/pcre/php_pcre.c:1.168.2.9.2.26 --- > php-src/ext/pcre/php_pcre.c:1.168.2.9.2.25 Wed Feb 20 22:08:18 2008 +++ > php-src/ext/pcre/php_pcre.c Fri Aug 8 09:34:08 2008 > @@ -16,7 +16,7 @@ > > +----------------------------------------------------------------------+ */ > > -/* $Id: php_pcre.c,v 1.168.2.9.2.25 2008/02/20 22:08:18 felipe Exp $ */ > +/* $Id: php_pcre.c,v 1.168.2.9.2.26 2008/08/08 09:34:08 lbarnaud Exp $ */ > > #include "php.h" > #include "php_ini.h" > @@ -174,6 +174,50 @@ > } > /* }}} */ > > +/* {{{ static make_subpats_table */ > +static char **make_subpats_table(int num_subpats, pcre_cache_entry *pce > TSRMLS_DC) +{ > + pcre_extra *extra = pce->extra; > + int name_cnt = 0, name_size, ni = 0; > + int rc; > + char *name_table; > + unsigned short name_idx; > + char **subpat_names = (char **)ecalloc(num_subpats, sizeof(char *)); > + > + rc = pcre_fullinfo(pce->re, extra, PCRE_INFO_NAMECOUNT, &name_cnt); > + if (rc < 0) { > + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal > pcre_fullinfo() > error %d", rc); + efree(subpat_names); > + return NULL; > + } > + if (name_cnt > 0) { > + int rc1, rc2; > + > + rc1 = pcre_fullinfo(pce->re, extra, PCRE_INFO_NAMETABLE, > &name_table); > + rc2 = pcre_fullinfo(pce->re, extra, PCRE_INFO_NAMEENTRYSIZE, > &name_size); + rc = rc2 ? rc2 : rc1; > + if (rc < 0) { > + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal > pcre_fullinfo() > error %d", rc); + efree(subpat_names); > + return NULL; > + } > + > + while (ni++ < name_cnt) { > + name_idx = 0xff * name_table[0] + name_table[1]; > + subpat_names[name_idx] = name_table + 2; > + if (is_numeric_string(subpat_names[name_idx], > strlen(subpat_names[name_idx]), NULL, NULL, 0) > 0) { > + php_error_docref(NULL TSRMLS_CC, E_WARNING, > "Numeric named subpatterns > are not allowed"); + efree(subpat_names); > + return NULL; > + } > + name_table += name_size; > + } > + } > + > + return subpat_names; > +} > +/* }}} */ > + > /* {{{ pcre_get_compiled_regex_cache > */ > PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int > regex_len TSRMLS_DC) @@ -484,7 +528,7 @@ > int g_notempty = 0; /* If the match > should not be empty */ > const char **stringlist; /* Holds list of > subpatterns */ > char *match; /* The current > match */ > - char **subpat_names = NULL;/* Array for named subpatterns > */ > + char **subpat_names; /* Array for named > subpatterns */ > int i, rc; > int subpats_order; /* Order of > subpattern matches */ > int offset_capture; /* Capture match > offsets: yes/no */ > @@ -539,54 +583,19 @@ > } > num_subpats++; > size_offsets = num_subpats * 3; > - offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0); > > /* > * Build a mapping from subpattern numbers to their names. We will > always > * allocate the table, even though there may be no named subpatterns. > This * avoids somewhat more complicated logic in the inner loops. > */ > - subpat_names = (char **)safe_emalloc(num_subpats, sizeof(char *), 0); > - memset(subpat_names, 0, sizeof(char *) * num_subpats); > - { > - int name_cnt = 0, name_size, ni = 0; > - char *name_table; > - unsigned short name_idx; > - > - rc = pcre_fullinfo(pce->re, extra, PCRE_INFO_NAMECOUNT, > &name_cnt); > - if (rc < 0) { > - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal > pcre_fullinfo() > error %d", rc); - efree(offsets); > - efree(subpat_names); > - RETURN_FALSE; > - } > - if (name_cnt > 0) { > - int rc1, rc2; > - > - rc1 = pcre_fullinfo(pce->re, extra, > PCRE_INFO_NAMETABLE, &name_table); > - rc2 = pcre_fullinfo(pce->re, extra, > PCRE_INFO_NAMEENTRYSIZE, > &name_size); - rc = rc2 ? rc2 : rc1; > - if (rc < 0) { > - php_error_docref(NULL TSRMLS_CC, E_WARNING, > "Internal pcre_fullinfo() > error %d", rc); - efree(offsets); > - efree(subpat_names); > - RETURN_FALSE; > - } > - > - while (ni++ < name_cnt) { > - name_idx = 0xff * name_table[0] + name_table[1]; > - subpat_names[name_idx] = name_table + 2; > - if (is_numeric_string(subpat_names[name_idx], > strlen(subpat_names[name_idx]), NULL, NULL, 0) > 0) { > - php_error_docref(NULL TSRMLS_CC, > E_WARNING, "Numeric named > subpatterns are not allowed"); - > efree(offsets); > - efree(subpat_names); > - RETURN_FALSE; > - } > - name_table += name_size; > - } > - } > + subpat_names = make_subpats_table(num_subpats, pce TSRMLS_CC); > + if (!subpat_names) { > + RETURN_FALSE; > } > > + offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0); > + > /* Allocate match sets array and initialize the values. */ > if (global && subpats_order == PREG_PATTERN_ORDER) { > match_sets = (zval **)safe_emalloc(num_subpats, sizeof(zval *), > 0); > @@ -794,7 +803,7 @@ > > /* {{{ preg_do_repl_func > */ > -static int preg_do_repl_func(zval *function, char *subject, int *offsets, > int count, char **result TSRMLS_DC) +static int preg_do_repl_func(zval > *function, char *subject, int *offsets, char **subpat_names, int count, > char **result TSRMLS_DC) { > zval *retval_ptr; /* Function return value */ > zval **args[1]; /* Argument to pass to function > */ > @@ -804,8 +813,12 @@ > > MAKE_STD_ZVAL(subpats); > array_init(subpats); > - for (i = 0; i < count; i++) > + for (i = 0; i < count; i++) { > + if (subpat_names[i]) { > + add_assoc_stringl(subpats, subpat_names[i], > &subject[offsets[i<<1]] , > offsets[(i<<1)+1] - offsets[i<<1], 1); + } > add_next_index_stringl(subpats, &subject[offsets[i<<1]], > offsets[(i<<1)+1] - offsets[i<<1], 1); + } > args[0] = &subpats; > > if (call_user_function_ex(EG(function_table), NULL, function, > &retval_ptr, 1, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { @@ > -944,6 +957,8 @@ > int exoptions = 0; /* Execution > options */ > int count = 0; /* > Count of matched subpatterns */ > int *offsets; /* > Array of subpattern offsets */ > + char **subpat_names; /* Array for named > subpatterns */ > + int num_subpats; /* Number of > captured subpatterns */ > int size_offsets; /* Size of the > offsets array */ > int new_len; /* > Length of needed storage */ > int alloc_len; /* > Actual allocated length */ > @@ -987,12 +1002,24 @@ > } > > /* Calculate the size of the offsets array, and allocate memory for it. > */ - rc = pcre_fullinfo(pce->re, extra, PCRE_INFO_CAPTURECOUNT, > &size_offsets); + rc = pcre_fullinfo(pce->re, extra, > PCRE_INFO_CAPTURECOUNT, &num_subpats); if (rc < 0) { > php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal > pcre_fullinfo() > error %d", rc); return NULL; > } > - size_offsets = (size_offsets + 1) * 3; > + num_subpats++; > + size_offsets = num_subpats * 3; > + > + /* > + * Build a mapping from subpattern numbers to their names. We will > always > + * allocate the table, even though there may be no named subpatterns. > This + * avoids somewhat more complicated logic in the inner loops. > + */ > + subpat_names = make_subpats_table(num_subpats, pce TSRMLS_CC); > + if (!subpat_names) { > + return NULL; > + } > + > offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0); > > alloc_len = 2 * subject_len + 1; > @@ -1033,8 +1060,7 @@ > new_len += eval_result_len; > } else if (is_callable_replace) { > /* Use custom function to get replacement > string and its length. */ > - eval_result_len = > preg_do_repl_func(replace_val, subject, offsets, > - > count, &eval_result TSRMLS_CC); > + eval_result_len = > preg_do_repl_func(replace_val, subject, offsets, > subpat_names, count, &eval_result TSRMLS_CC); new_len += eval_result_len; > } else { /* do regular substitution */ > walk = replace; > @@ -1149,8 +1175,9 @@ > /* Advance to the next piece. */ > start_offset = offsets[1]; > } > - > + > efree(offsets); > + efree(subpat_names); > > return result; > } > > http://cvs.php.net/viewvc.cgi/php-src/ext/pcre/tests/bug37911.phpt?view=mar >kup&rev=1.1 Index: php-src/ext/pcre/tests/bug37911.phpt > +++ php-src/ext/pcre/tests/bug37911.phpt -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php