]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6'
authorChristoph M. Becker <cmb@php.net>
Tue, 23 Jun 2015 14:50:52 +0000 (16:50 +0200)
committerChristoph M. Becker <cmb@php.net>
Tue, 23 Jun 2015 14:50:52 +0000 (16:50 +0200)
* PHP-5.6:
  Fixed bug #69864 (Segfault in preg_replace_callback)

1  2 
ext/pcre/php_pcre.c

index 11b74b45b3be084a61479ca436ea111005943ad3,181b633c39cf136e059685f6dadcf4ebae21026a..418859f5d2ffd1de0d211060f66acd3e58028450
@@@ -185,15 -167,16 +185,16 @@@ static PHP_MSHUTDOWN_FUNCTION(pcre
  /* }}} */
  
  /* {{{ static pcre_clean_cache */
 -static int pcre_clean_cache(void *data, void *arg TSRMLS_DC)
 +static int pcre_clean_cache(zval *data, void *arg)
  {
 -      pcre_cache_entry *pce = (pcre_cache_entry *) data;
++      pcre_cache_entry *pce = (pcre_cache_entry *) Z_PTR_P(data);
        int *num_clean = (int *)arg;
  
-       if (*num_clean > 0) {
+       if (*num_clean > 0 && !pce->refcount) {
                (*num_clean)--;
-               return 1;
+               return ZEND_HASH_APPLY_REMOVE;
        } else {
-               return 0;
+               return ZEND_HASH_APPLY_KEEP;
        }
  }
  /* }}} */
@@@ -454,26 -444,11 +455,27 @@@ PHPAPI pcre_cache_entry* pcre_get_compi
        new_entry.preg_options = poptions;
        new_entry.compile_options = coptions;
  #if HAVE_SETLOCALE
 -      new_entry.locale = pestrdup(locale, 1);
 +      new_entry.locale = BG(locale_string) ?
 +              ((GC_FLAGS(BG(locale_string)) & IS_STR_PERSISTENT) ?
 +                      zend_string_copy(BG(locale_string)) :
 +                      zend_string_init(BG(locale_string)->val, BG(locale_string)->len, 1)) :
 +              NULL;
        new_entry.tables = tables;
  #endif
+       new_entry.refcount = 0;
  
 +      rc = pcre_fullinfo(re, extra, PCRE_INFO_CAPTURECOUNT, &new_entry.capture_count);
 +      if (rc < 0) {
 +              php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc);
 +              return NULL;
 +      }
 +
 +      rc = pcre_fullinfo(re, extra, PCRE_INFO_NAMECOUNT, &new_entry.name_count);
 +      if (rc < 0) {
 +              php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc);
 +              return NULL;
 +      }
 +
        /*
         * Interned strings are not duplicated when stored in HashTable,
         * but all the interned strings created during HTTP request are removed
@@@ -584,8 -552,10 +586,10 @@@ static void php_do_pcre_match(INTERNAL_
                RETURN_FALSE;
        }
  
 -      php_pcre_match_impl(pce, subject, subject_len, return_value, subpats, 
 -              global, ZEND_NUM_ARGS() >= 4, flags, start_offset TSRMLS_CC);
+       pce->refcount++;
 +      php_pcre_match_impl(pce, subject->val, (int)subject->len, return_value, subpats,
 +              global, ZEND_NUM_ARGS() >= 4, flags, start_offset);
+       pce->refcount--;
  }
  /* }}} */
  
@@@ -1010,21 -1015,24 +1014,25 @@@ static zend_string *preg_do_repl_func(z
  
  /* {{{ php_pcre_replace
   */
 -PHPAPI char *php_pcre_replace(char *regex,   int regex_len,
 +PHPAPI zend_string *php_pcre_replace(zend_string *regex,
 +                                                        zend_string *subject_str,
                                                          char *subject, int subject_len,
                                                          zval *replace_val, int is_callable_replace,
 -                                                        int *result_len, int limit, int *replace_count TSRMLS_DC)
 +                                                        int limit, int *replace_count)
  {
        pcre_cache_entry        *pce;                       /* Compiled regular expression */
 -      char                            *result;                        /* Function result */
++      zend_string                     *result;                        /* Function result */
  
        /* Compile regex or get it from cache. */
 -      if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
 +      if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) {
                return NULL;
        }
-       return php_pcre_replace_impl(pce, subject_str, subject, subject_len, replace_val,
+       pce->refcount++;
 -      result = php_pcre_replace_impl(pce, subject, subject_len, replace_val, 
 -              is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
++      result = php_pcre_replace_impl(pce, subject_str, subject, subject_len, replace_val,
 +              is_callable_replace, limit, replace_count);
+       pce->refcount--;
+       return result;
  }
  /* }}} */
  
@@@ -1660,7 -1519,9 +1668,9 @@@ static PHP_FUNCTION(preg_split
                RETURN_FALSE;
        }
  
 -      php_pcre_split_impl(pce, subject, subject_len, return_value, limit_val, flags TSRMLS_CC);
+       pce->refcount++;
 +      php_pcre_split_impl(pce, subject->val, (int)subject->len, return_value, (int)limit_val, flags);
+       pce->refcount--;
  }
  /* }}} */
  
@@@ -1967,7 -1805,9 +1977,9 @@@ static PHP_FUNCTION(preg_grep
                RETURN_FALSE;
        }
  
 -      php_pcre_grep_impl(pce, input, return_value, flags TSRMLS_CC);
+       pce->refcount++;
 +      php_pcre_grep_impl(pce, input, return_value, flags);
+       pce->refcount--;
  }
  /* }}} */