]> granicus.if.org Git - php/commitdiff
Fix #73612: preg_*() may leak memory
authorChristoph M. Becker <cmbecker69@gmx.de>
Sat, 26 Nov 2016 14:34:27 +0000 (15:34 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Sat, 26 Nov 2016 14:34:27 +0000 (15:34 +0100)
We have to make sure that collectible zvals end up in the GC root
buffer, to avoid memory leaks.

NEWS
ext/pcre/php_pcre.c
ext/pcre/tests/bug73612.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 9bffebb6ccb1efa20753652179f4de6780873a9a..9226c51cb7a54551e70a5dd08a0d785cc4a4a380 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ PHP                                                                        NEWS
   . Fixed bug #73585 (Logging of "Internal Zend error - Missing class
     information" missing class name). (Laruence)
 
+- PCRE:
+  . Fixed bug #73612 (preg_*() may leak memory). (cmb)
+
 08 Dec 2016 PHP 7.0.14
 
 - Core:
index 8601b731f5ba4ed9513b0fcf70f939e982770f67..af1916aa450fb07581e97ea29b45ddf121c76e40 100644 (file)
@@ -726,7 +726,7 @@ 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_ptr_dtor(subpats);
                array_init(subpats);
        }
 
@@ -1592,7 +1592,7 @@ static PHP_FUNCTION(preg_replace)
 
        replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 0, 0);
        if (zcount) {
-               zval_dtor(zcount);
+               zval_ptr_dtor(zcount);
                ZVAL_LONG(zcount, replace_count);
        }
 }
@@ -1627,7 +1627,7 @@ static PHP_FUNCTION(preg_replace_callback)
 
        replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 1, 0);
        if (zcount) {
-               zval_dtor(zcount);
+               zval_ptr_dtor(zcount);
                ZVAL_LONG(zcount, replace_count);
        }
 }
@@ -1689,7 +1689,7 @@ static PHP_FUNCTION(preg_replace_callback_array)
        } ZEND_HASH_FOREACH_END();
 
        if (zcount) {
-               zval_dtor(zcount);
+               zval_ptr_dtor(zcount);
                ZVAL_LONG(zcount, replace_count);
        }
 }
@@ -1720,7 +1720,7 @@ static PHP_FUNCTION(preg_filter)
 
        replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 0, 1);
        if (zcount) {
-               zval_dtor(zcount);
+               zval_ptr_dtor(zcount);
                ZVAL_LONG(zcount, replace_count);
        }
 }
diff --git a/ext/pcre/tests/bug73612.phpt b/ext/pcre/tests/bug73612.phpt
new file mode 100644 (file)
index 0000000..707e10b
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--\r
+Bug #73612 (preg_*() may leak memory)\r
+--FILE--\r
+<?php\r
+$obj = new stdClass;\r
+$obj->obj = $obj;\r
+preg_match('/./', 'x', $obj);\r
+\r
+$obj = new stdClass;\r
+$obj->obj = $obj;\r
+preg_replace('/./', '', 'x', -1, $obj);\r
+\r
+$obj = new stdClass;\r
+$obj->obj = $obj;\r
+preg_replace_callback('/./', 'count', 'x', -1, $obj);\r
+\r
+$obj = new stdClass;\r
+$obj->obj = $obj;\r
+preg_replace_callback_array(['/./' => 'count'], 'x', -1, $obj);\r
+\r
+$obj = new stdClass;\r
+$obj->obj = $obj;\r
+preg_filter('/./', '', 'x', -1, $obj);\r
+?>\r
+===DONE===\r
+--EXPECT--\r
+===DONE===\r