]> granicus.if.org Git - php/commitdiff
Fixed bug #44925 (preg_grep() modifies input array)
authorNuno Lopes <nlopess@php.net>
Thu, 14 Aug 2008 13:12:42 +0000 (13:12 +0000)
committerNuno Lopes <nlopess@php.net>
Thu, 14 Aug 2008 13:12:42 +0000 (13:12 +0000)
NEWS
ext/pcre/php_pcre.c
ext/pcre/tests/bug44925.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index bc885b9d0a33b6e0f9f4776a3c50b81f62603009..3b66b1f7c74e46722bfe9f5e06faa61f1ce7b5b4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,7 @@ PHP                                                                        NEWS
 - Fixed bug #45545 (DateInterval has 4 char limitation for ISO durations).
   (Derick)
 - Fixed bug #45044 (relative paths not resolved correctly). (Dmitry)
+- Fixed bug #44925 (preg_grep() modifies input array). (Nuno)
 - Fixed bug #44100 (Inconsistent handling of static array declarations with
   duplicate keys). (Dmitry)
 - Fixed bug #43817 (opendir() fails on Windows directories with parent
index 0e15793475de8ad05636a4076e6758ebbc61f7d6..8d6b2eaffd2471c6374c69a4568045cc23a14caf 100644 (file)
@@ -1743,13 +1743,30 @@ PHPAPI void  php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
 
        /* Go through the input array */
        zend_hash_internal_pointer_reset(Z_ARRVAL_P(input));
-       while(zend_hash_get_current_data(Z_ARRVAL_P(input), (void **)&entry) == SUCCESS) {
+       while (zend_hash_get_current_data(Z_ARRVAL_P(input), (void **)&entry) == SUCCESS) {
+               zend_bool is_copy;
+               zval *str;
+
+               switch (Z_TYPE_PP(entry)) {
+                       case IS_STRING:
+                               is_copy = 0;
+                               str = *entry;
+                               break;
+
+                       default:
+                               is_copy = 1;
 
-               convert_to_string_ex(entry);
+                               ALLOC_ZVAL(str);
+                               Z_ADDREF_PP(entry); /* the function below decreases the ref counting */
+                               COPY_PZVAL_TO_ZVAL(*str, *entry);
+
+                               convert_to_string(str);
+                               break;
+               }
 
                /* Perform the match */
-               count = pcre_exec(pce->re, extra, Z_STRVAL_PP(entry),
-                                                 Z_STRLEN_PP(entry), 0,
+               count = pcre_exec(pce->re, extra, Z_STRVAL_P(str),
+                                                 Z_STRLEN_P(str), 0,
                                                  0, offsets, size_offsets);
 
                /* Check for too many substrings condition. */
@@ -1762,25 +1779,30 @@ PHPAPI void  php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return
                }
 
                /* If the entry fits our requirements */
-               if ((count > 0 && !invert) ||
-                       (count == PCRE_ERROR_NOMATCH && invert)) {
-                       Z_ADDREF_PP(entry);
+               if ((count > 0 && !invert) || (count == PCRE_ERROR_NOMATCH && invert)) {
+
+                       if (!is_copy) {
+                               SEPARATE_ARG_IF_REF(str);
+                       }
 
                        /* Add to return array */
                        switch (zend_hash_get_current_key(Z_ARRVAL_P(input), &string_key, &num_key, 0))
                        {
                                case HASH_KEY_IS_STRING:
                                        zend_hash_update(Z_ARRVAL_P(return_value), string_key,
-                                                                        strlen(string_key)+1, entry, sizeof(zval *), NULL);
+                                                                        strlen(string_key)+1, &str, sizeof(zval *), NULL);
                                        break;
 
                                case HASH_KEY_IS_LONG:
-                                       zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry,
+                                       zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, &str,
                                                                                   sizeof(zval *), NULL);
                                        break;
                        }
+               } else if (is_copy) {
+                       zval_dtor(str);
+                       FREE_ZVAL(str);
                }
-               
+
                zend_hash_move_forward(Z_ARRVAL_P(input));
        }
        zend_hash_internal_pointer_reset(Z_ARRVAL_P(input));
diff --git a/ext/pcre/tests/bug44925.phpt b/ext/pcre/tests/bug44925.phpt
new file mode 100644 (file)
index 0000000..828d245
--- /dev/null
@@ -0,0 +1,105 @@
+--TEST--
+Bug #44925 (preg_grep() modifies input array)
+--FILE--
+<?php
+$str1 = 'a';
+$str2 = 'b';
+
+$array=Array("1",2,3,1.1,FALSE,NULL,Array(), $str1, &$str2);
+
+var_dump($array);
+
+var_dump(preg_grep('/do not match/',$array));
+
+$a = preg_grep('/./',$array);
+var_dump($a);
+
+$str1 = 'x';
+$str2 = 'y';
+
+var_dump($a); // check if array is still ok
+
+var_dump($array);
+
+?>
+--EXPECTF--
+array(9) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  float(1.1)
+  [4]=>
+  bool(false)
+  [5]=>
+  NULL
+  [6]=>
+  array(0) {
+  }
+  [7]=>
+  string(1) "a"
+  [8]=>
+  &string(1) "b"
+}
+
+Notice: Array to string conversion in %sbug44925.php on line 9
+array(0) {
+}
+
+Notice: Array to string conversion in %sbug44925.php on line 11
+array(7) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  string(1) "2"
+  [2]=>
+  string(1) "3"
+  [3]=>
+  string(3) "1.1"
+  [6]=>
+  string(5) "Array"
+  [7]=>
+  string(1) "a"
+  [8]=>
+  string(1) "b"
+}
+array(7) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  string(1) "2"
+  [2]=>
+  string(1) "3"
+  [3]=>
+  string(3) "1.1"
+  [6]=>
+  string(5) "Array"
+  [7]=>
+  string(1) "a"
+  [8]=>
+  string(1) "b"
+}
+array(9) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  float(1.1)
+  [4]=>
+  bool(false)
+  [5]=>
+  NULL
+  [6]=>
+  array(0) {
+  }
+  [7]=>
+  string(1) "a"
+  [8]=>
+  &string(1) "y"
+}