summaryrefslogtreecommitdiff
path: root/ext/pcre
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pcre')
-rw-r--r--ext/pcre/php_pcre.c3
-rw-r--r--ext/pcre/tests/bug63055.phpt23
2 files changed, 25 insertions, 1 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index b1b9e66e9a..1af8151251 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -547,8 +547,9 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
/* Overwrite the passed-in value for subpatterns with an empty array. */
if (subpats != NULL) {
- zval_dtor(subpats);
+ zval garbage = *subpats;
array_init(subpats);
+ zval_dtor(&garbage);
}
subpats_order = global ? PREG_PATTERN_ORDER : 0;
diff --git a/ext/pcre/tests/bug63055.phpt b/ext/pcre/tests/bug63055.phpt
new file mode 100644
index 0000000000..16c50b54e5
--- /dev/null
+++ b/ext/pcre/tests/bug63055.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #63055 (Segfault in zend_gc with SF2 testsuite)
+--FILE--
+<?php
+/* the default gc root size is 10,000 */
+for ($i=0; $i<9998; $i++) {
+ $array = array();
+ $array[0] = &$array;
+ unset($array);
+}
+
+$matches = array("foo" => "bar"); /* this bucket will trigger the segfault */
+$dummy = array("dummy"); /* used to trigger gc_collect_cycles */
+$dummy[1] = &$dummy;
+
+$matches[1] = &$matches;
+$matches[2] = $dummy;
+
+preg_match_all("/(\d)+/", "foo123456bar", $matches);
+echo "okey";
+?>
+--EXPECTF--
+okey