]> granicus.if.org Git - php/commitdiff
Fixed bug #68128
authorTjerk Meesters <datibbaw@php.net>
Mon, 6 Oct 2014 01:40:39 +0000 (09:40 +0800)
committerTjerk Meesters <datibbaw@php.net>
Tue, 14 Oct 2014 14:49:01 +0000 (22:49 +0800)
Three issues are addressed:

- RecursiveRegexIterator::accept() should accept non-empty arrays without
  applying any regular expression and RegexIterator::accept() should not accept
  an array.
- RegexIterator::accept() should not accept an atom that fails to match
  anything, even when PREG_PATTERN_ORDER is used (which would return an array
  of empty arrays).
- RecursiveRegexIterator::getChildren() should pass all constructor arguments
  to its child iterator instead of just the regular expression.

NEWS
ext/spl/spl_engine.h
ext/spl/spl_iterators.c
ext/spl/tests/bug68128.phpt [new file with mode: 0644]
ext/spl/tests/iterator_048.phpt
ext/spl/tests/iterator_050.phpt
ext/spl/tests/iterator_052.phpt
ext/spl/tests/iterator_053.phpt
ext/spl/tests/iterator_054.phpt

diff --git a/NEWS b/NEWS
index cb69e029a263e98653ce6f3e405382b629fce058..aa8cb7ebf4dccbefb16f0caef6a1bcc28eb36161 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ PHP                                                                        NEWS
 - ODBC:
   . Fixed bug #68087 (ODBC not correctly reading DATE column when preceded by
     a VARCHAR column) (Keyur Govande)
+- SPL:
+  . Fixed bug #68128 (Regression in RecursiveRegexIterator) (Tjerk)
 
 ?? ??? 2014, PHP 5.5.18
 
index a67e60c1051d5692a80fc0376052d9bf2c39c087..473438bb7a198db94043a7f3af79e94b18790e17 100644 (file)
@@ -49,6 +49,41 @@ static inline int spl_instantiate_arg_ex2(zend_class_entry *pce, zval **retval,
 }
 /* }}} */
 
+/* {{{ spl_instantiate_arg_n */
+static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval **retval, int argc, zval ***argv TSRMLS_DC)
+{
+       zend_function *func = pce->constructor;
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcc;
+       zval *dummy;
+       zval z_name;
+
+       spl_instantiate(pce, retval, 0 TSRMLS_CC);
+
+       ZVAL_STRING(&z_name, func->common.function_name, 0);
+
+       fci.size = sizeof(zend_fcall_info);
+       fci.function_table = &pce->function_table;
+       fci.function_name = &z_name;
+       fci.object_ptr = *retval;
+       fci.symbol_table = NULL;
+       fci.retval_ptr_ptr = &dummy;
+       fci.param_count = argc;
+       fci.params = argv;
+       fci.no_separation = 1;
+
+       fcc.initialized = 1;
+       fcc.function_handler = func;
+       fcc.calling_scope = EG(scope);
+       fcc.called_scope = pce;
+       fcc.object_ptr = *retval;
+
+       zend_call_function(&fci, &fcc TSRMLS_CC);
+
+       zval_ptr_dtor(&dummy);
+}
+/* }}} */
+
 #endif /* SPL_ENGINE_H */
 
 /*
index 87a448ca64eb155c2e23f160cb2eaba857a3e0ce..71e03b4514fb1f8ec06c65456051336708489142 100644 (file)
@@ -1979,8 +1979,10 @@ SPL_METHOD(RegexIterator, accept)
        
        if (intern->current.data == NULL) {
                RETURN_FALSE;
+       } else if (Z_TYPE_P(intern->current.data) == IS_ARRAY) {
+               RETURN_FALSE;
        }
-       
+
        if (intern->u.regex.flags & REGIT_USE_KEY) {
                subject_ptr = intern->current.key;
        } else {
@@ -2014,8 +2016,7 @@ SPL_METHOD(RegexIterator, accept)
                ALLOC_INIT_ZVAL(intern->current.data);
                php_pcre_match_impl(intern->u.regex.pce, subject, subject_len, &zcount, 
                        intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0 TSRMLS_CC);
-               count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data));
-               RETVAL_BOOL(count > 0);
+               RETVAL_BOOL(Z_LVAL(zcount) > 0);
                break;
 
        case REGIT_MODE_SPLIT:
@@ -2193,7 +2194,7 @@ SPL_METHOD(RecursiveRegexIterator, __construct)
 SPL_METHOD(RecursiveRegexIterator, getChildren)
 {
        spl_dual_it_object   *intern;
-       zval                 *retval, *regex;
+       zval                 *retval;
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
@@ -2203,16 +2204,61 @@ SPL_METHOD(RecursiveRegexIterator, getChildren)
 
        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
        if (!EG(exception)) {
+               zval **args[5], *object, *regex, *mode, *flags, *preg_flags;
+
+               MAKE_STD_ZVAL(object);
                MAKE_STD_ZVAL(regex);
+               MAKE_STD_ZVAL(mode);
+               MAKE_STD_ZVAL(flags);
+               MAKE_STD_ZVAL(preg_flags);
+
+               MAKE_COPY_ZVAL(&retval, object);
                ZVAL_STRING(regex, intern->u.regex.regex, 1);
-               spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, regex TSRMLS_CC);
+               ZVAL_LONG(mode, intern->u.regex.mode);
+               ZVAL_LONG(flags, intern->u.regex.flags);
+               ZVAL_LONG(preg_flags, intern->u.regex.preg_flags);
+
+               args[0] = &object;
+               args[1] = &regex;
+               args[2] = &mode;
+               args[3] = &flags;
+               args[4] = &preg_flags;
+
+               spl_instantiate_arg_n(Z_OBJCE_P(getThis()), &return_value, 5, args TSRMLS_CC);
+
+               zval_ptr_dtor(&object);
                zval_ptr_dtor(&regex);
+               zval_ptr_dtor(&mode);
+               zval_ptr_dtor(&flags);
+               zval_ptr_dtor(&preg_flags);
        }
        if (retval) {
                zval_ptr_dtor(&retval);
        }
 } /* }}} */
 
+SPL_METHOD(RecursiveRegexIterator, accept)
+{
+       spl_dual_it_object *intern;
+       zval *rv;
+
+       if (zend_parse_parameters_none() == FAILURE) {
+               return;
+       }
+
+       SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
+
+       if (intern->current.data == NULL) {
+               RETURN_FALSE;
+       } else if (Z_TYPE_P(intern->current.data) == IS_ARRAY) {
+               RETURN_BOOL(zend_hash_num_elements(Z_ARRVAL_P(intern->current.data)) > 0);
+       }
+
+       zend_call_method_with_0_params(&(getThis()), spl_ce_RegexIterator, NULL, "accept", &rv);
+
+       RETURN_ZVAL(rv, 1, 1);
+}
+
 #endif
 
 /* {{{ spl_dual_it_dtor */
@@ -2403,6 +2449,7 @@ ZEND_END_ARG_INFO();
 
 static const zend_function_entry spl_funcs_RecursiveRegexIterator[] = {
        SPL_ME(RecursiveRegexIterator,  __construct,      arginfo_rec_regex_it___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveRegexIterator,  accept,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveFilterIterator, hasChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveRegexIterator,  getChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        PHP_FE_END
diff --git a/ext/spl/tests/bug68128.phpt b/ext/spl/tests/bug68128.phpt
new file mode 100644 (file)
index 0000000..ff41dd4
--- /dev/null
@@ -0,0 +1,91 @@
+--TEST--
+Bug #68128 - RecursiveRegexIterator raises "Array to string conversion" notice
+--FILE--
+<?php
+
+$array = new ArrayIterator(array('a', array('b', 'c')));
+$regex = new RegexIterator($array, '/Array/');
+
+foreach ($regex as $match) {
+    var_dump($match);
+}
+
+$rArrayIterator = new RecursiveArrayIterator(array('test1', array('tet3', 'test4', 'test5')));
+$rRegexIterator = new RecursiveRegexIterator($rArrayIterator, '/^(t)est(\d*)/',
+    RecursiveRegexIterator::ALL_MATCHES, 0, PREG_PATTERN_ORDER);
+
+foreach ($rRegexIterator as $key1 => $value1) {
+
+    if ($rRegexIterator->hasChildren()) {
+
+        // print all children
+        echo "Children: ";
+        foreach ($rRegexIterator->getChildren() as $key => $value) {
+                       print_r($value);
+        }
+        echo "\n";
+    } else {
+        echo "No children ";
+               print_r($value1);
+               echo "\n";
+    }
+}
+
+?>
+--EXPECT--
+No children Array
+(
+    [0] => Array
+        (
+            [0] => test1
+        )
+
+    [1] => Array
+        (
+            [0] => t
+        )
+
+    [2] => Array
+        (
+            [0] => 1
+        )
+
+)
+
+Children: Array
+(
+    [0] => Array
+        (
+            [0] => test4
+        )
+
+    [1] => Array
+        (
+            [0] => t
+        )
+
+    [2] => Array
+        (
+            [0] => 4
+        )
+
+)
+Array
+(
+    [0] => Array
+        (
+            [0] => test5
+        )
+
+    [1] => Array
+        (
+            [0] => t
+        )
+
+    [2] => Array
+        (
+            [0] => 5
+        )
+
+)
+
index bad4e7888a78ae96558dd5aed46d8172e34c9900..64ca97f4d65c43c7dfdbb8b5313d477aa86e8b2a 100644 (file)
@@ -13,11 +13,6 @@ class MyRecursiveRegexIterator extends RecursiveRegexIterator
                        var_dump($v);
                }
        }
-
-       function accept()
-       {
-               return $this->hasChildren() || parent::accept();
-       }
 }
 
 $ar = new RecursiveArrayIterator(array('Foo', array('Bar'), 'FooBar', array('Baz'), 'Biz'));
index fed4a3b2ee3c21e992c699cf88d8ef242dcfe5b9..63d8fbfa9a8f7292c549d029c29f013730a77992 100644 (file)
@@ -46,8 +46,6 @@ array(3) {
   [2]=>
   %s(1) "2"
 }
-
-Notice: Array to string conversion in %siterator_050.php on line %d
 int(0)
 array(2) {
   [0]=>
@@ -69,8 +67,6 @@ array(2) {
   [1]=>
   %s(1) "1"
 }
-
-Notice: Array to string conversion in %siterator_050.php on line %d
 object(ArrayIterator)#%d (1) {
   %s"storage"%s"ArrayIterator":private]=>
   array(9) {
index c68bd5234ded7e3b786152b277e510842530c14c..84b3eb993cd80c96a7804e0b8791c14f6fcedd72 100644 (file)
@@ -46,18 +46,6 @@ var_dump($ar);
 <?php exit(0); ?>
 --EXPECTF--
 bool(true)
-int(0)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
 int(1)
 array(3) {
@@ -97,85 +85,11 @@ array(3) {
   }
 }
 bool(true)
-int(3)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(4)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
-
-Notice: Array to string conversion in %siterator_052.php on line %d
+bool(false)
 bool(true)
-int(5)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(6)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(7)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
-bool(true)
-int(8)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
 int(0)
 array(2) {
@@ -231,67 +145,11 @@ array(2) {
   }
 }
 bool(true)
-int(3)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
-bool(true)
-int(4)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
-
-Notice: Array to string conversion in %siterator_052.php on line %d
 bool(true)
-int(5)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
+bool(false)
 bool(true)
-int(6)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
 bool(true)
-int(7)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
 bool(true)
-int(8)
-array(2) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-}
 object(ArrayIterator)#%d (1) {
   ["storage":"ArrayIterator":private]=>
   array(9) {
index 5d9c740c3127eba4e386ee01c475c2eb3792f225..b472523ab6607cfe14bce659344b56a44368d597 100644 (file)
@@ -46,122 +46,14 @@ var_dump($ar);
 <?php exit(0); ?>
 --EXPECTF--
 bool(true)
-int(0)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(1)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(2)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
-bool(true)
-int(3)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(4)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(5)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
+bool(false)
 bool(true)
-int(6)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(7)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
-int(8)
-array(3) {
-  [0]=>
-  array(0) {
-  }
-  [1]=>
-  array(0) {
-  }
-  [2]=>
-  array(0) {
-  }
-}
 bool(true)
 int(0)
 array(2) {
@@ -232,20 +124,7 @@ array(2) {
     string(1) "4"
   }
 }
-bool(true)
-int(5)
-array(2) {
-  [0]=>
-  array(1) {
-    [0]=>
-    string(1) "5"
-  }
-  [1]=>
-  array(1) {
-    [0]=>
-    string(1) "5"
-  }
-}
+bool(false)
 bool(true)
 int(6)
 array(2) {
index 1f1cd580c17fdf4f7f7d8db41051c29e24b3d9a6..91266c95711d4292e26f44bcaeb8c10da69704c8 100644 (file)
@@ -42,8 +42,6 @@ array(3) {
   [2]=>
   string(1) "3"
 }
-
-Notice: Array to string conversion in %siterator_054.php on line %d
 int(7)
 array(2) {
   [0]=>