]> granicus.if.org Git - php/commitdiff
Don't allow separation in array functions
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 07:08:56 +0000 (09:08 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 07:15:43 +0000 (09:15 +0200)
The only case here that might be *somewhat* sensible is the userdata
argument of array_walk(), which could be used to keep persistent state
between callback invokations -- with the WTF moment that the final
result after the walk finishes will be unchanged. Nowdays, this is
much better achieved using a closure with a use-by-reference.

ext/standard/array.c
ext/standard/tests/array/array_filter_variation7.phpt
ext/standard/tests/array/array_map_variation2.phpt
ext/standard/tests/array/array_user_key_compare.phpt
ext/standard/tests/array/array_walk_closure.phpt
ext/standard/tests/array/bug28739.phpt
ext/standard/tests/array/bug39576.phpt
ext/standard/tests/array/bug52719.phpt
ext/standard/tests/array/uasort_variation7.phpt
ext/standard/tests/array/uasort_variation9.phpt [deleted file]
ext/standard/tests/array/usort_variation7.phpt

index 530e72c4af3d5299948383d7ea7cd586347c957f..3eb06bd3c430545a7054d94be45d5bbbd1ba327d 100644 (file)
@@ -921,7 +921,7 @@ static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s) /* {{{ *
        BG(user_compare_fci).param_count = 2;
        BG(user_compare_fci).params = args;
        BG(user_compare_fci).retval = &retval;
-       BG(user_compare_fci).no_separation = 0;
+       BG(user_compare_fci).no_separation = 1;
        call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
        zval_ptr_dtor(&args[1]);
        zval_ptr_dtor(&args[0]);
@@ -1063,7 +1063,7 @@ static inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s) /* {
        BG(user_compare_fci).param_count = 2;
        BG(user_compare_fci).params = args;
        BG(user_compare_fci).retval = &retval;
-       BG(user_compare_fci).no_separation = 0;
+       BG(user_compare_fci).no_separation = 1;
        call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
        zval_ptr_dtor(&args[1]);
        zval_ptr_dtor(&args[0]);
@@ -1374,7 +1374,7 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
        BG(array_walk_fci).retval = &retval;
        BG(array_walk_fci).param_count = userdata ? 3 : 2;
        BG(array_walk_fci).params = args;
-       BG(array_walk_fci).no_separation = 0;
+       BG(array_walk_fci).no_separation = 1;
 
        zend_hash_internal_pointer_reset_ex(target_hash, &pos);
        ht_iter = zend_hash_iterator_add(target_hash, pos);
@@ -4546,7 +4546,7 @@ static int zval_user_compare(zval *a, zval *b) /* {{{ */
        BG(user_compare_fci).param_count = 2;
        BG(user_compare_fci).params = args;
        BG(user_compare_fci).retval = &retval;
-       BG(user_compare_fci).no_separation = 0;
+       BG(user_compare_fci).no_separation = 1;
 
        if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
                zend_long ret = zval_get_long(&retval);
@@ -5906,7 +5906,7 @@ PHP_FUNCTION(array_reduce)
 
        fci.retval = &retval;
        fci.param_count = 2;
-       fci.no_separation = 0;
+       fci.no_separation = 1;
 
        ZEND_HASH_FOREACH_VAL(htbl, operand) {
                ZVAL_COPY_VALUE(&args[0], return_value);
@@ -5959,7 +5959,7 @@ PHP_FUNCTION(array_filter)
 
        if (ZEND_FCI_INITIALIZED(fci)) {
                have_callback = 1;
-               fci.no_separation = 0;
+               fci.no_separation = 1;
                fci.retval = &retval;
                if (use_type == ARRAY_FILTER_USE_BOTH) {
                        fci.param_count = 2;
@@ -6062,7 +6062,7 @@ PHP_FUNCTION(array_map)
                        fci.retval = &result;
                        fci.param_count = 1;
                        fci.params = &arg;
-                       fci.no_separation = 0;
+                       fci.no_separation = 1;
 
                        ZVAL_COPY(&arg, zv);
                        ret = zend_call_function(&fci, &fci_cache);
@@ -6151,7 +6151,7 @@ PHP_FUNCTION(array_map)
                                fci.retval = &result;
                                fci.param_count = n_arrays;
                                fci.params = params;
-                               fci.no_separation = 0;
+                               fci.no_separation = 1;
 
                                if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
                                        efree(array_pos);
index d2a6255160f9644639299009807267a79911abec..805f31424498b2fcc003e972555d63feb3ddbb05 100644 (file)
@@ -14,10 +14,6 @@ $input = array(0, 1, -1, 10, 100, 1000, 'Hello', null);
 echo "Anonymous callback function with regular parameter and statement\n";
 var_dump( array_filter($input, function($input) { return ($input > 1); }) );
 
-// anonymous callback function with reference
-echo "Anonymous callback function with reference parameter\n";
-var_dump( array_filter($input, function(&$input) { return ($input < 1); }) );
-
 // anonymous callback function with null argument
 echo "Anonymous callback function with null argument\n";
 var_dump( array_filter($input, function() { return true; }) );
@@ -39,17 +35,6 @@ array(3) {
   [5]=>
   int(1000)
 }
-Anonymous callback function with reference parameter
-array(4) {
-  [0]=>
-  int(0)
-  [2]=>
-  int(-1)
-  [6]=>
-  string(5) "Hello"
-  [7]=>
-  NULL
-}
 Anonymous callback function with null argument
 array(8) {
   [0]=>
index 0d93b33c81653a6e0f0b2d3f2d4ae3df4765e9bc..c88e6fb2e98d7b43b7d3ba430b5f89101ffa672c 100644 (file)
@@ -8,9 +8,7 @@ $arr = array("k1" => "v1","k2"=>"v2");
 $arr[]=&$arr["k1"];
 $arr[]=&$arr;
 function cb1 ($a) {var_dump ($a);return array ($a);};
-function cb2 (&$a) {var_dump ($a);return array (&$a);};
 var_dump( array_map("cb1", $arr));
-var_dump( array_map("cb2", $arr,$arr));
 var_dump( array_map(null,  $arr));
 var_dump( array_map(null, $arr, $arr));
 
@@ -66,50 +64,6 @@ array(4) {
     }
   }
 }
-string(2) "v1"
-string(2) "v2"
-string(2) "v1"
-array(4) {
-  ["k1"]=>
-  &string(2) "v1"
-  ["k2"]=>
-  string(2) "v2"
-  [0]=>
-  &string(2) "v1"
-  [1]=>
-  *RECURSION*
-}
-array(4) {
-  [0]=>
-  array(1) {
-    [0]=>
-    &string(2) "v1"
-  }
-  [1]=>
-  array(1) {
-    [0]=>
-    string(2) "v2"
-  }
-  [2]=>
-  array(1) {
-    [0]=>
-    &string(2) "v1"
-  }
-  [3]=>
-  array(1) {
-    [0]=>
-    &array(4) {
-      ["k1"]=>
-      &string(2) "v1"
-      ["k2"]=>
-      string(2) "v2"
-      [0]=>
-      &string(2) "v1"
-      [1]=>
-      *RECURSION*
-    }
-  }
-}
 array(4) {
   ["k1"]=>
   &string(2) "v1"
index 69bc37f48a4e496b29473b2d2293f94999329fe2..3901c3d2e2a63ce5f751a2a24cdb6221c2d34476 100644 (file)
@@ -15,5 +15,8 @@ uksort($arr, "array_compare");
 var_dump($a);
 
 ?>
---EXPECT--
+--EXPECTF--
+Warning: array_compare(): Argument #1 ($key1) must be passed by reference, value given in %s on line %d
+
+Warning: array_compare(): Argument #2 ($key2) must be passed by reference, value given in %s on line %d
 string(1) "B"
index 6cc49cf9d37376449b4a3619e7e7da204de99937..68e56568e7c782041759a2f55ae0d4cad2fa11b1 100644 (file)
@@ -107,17 +107,23 @@ array(2) {
 bool(true)
 
 closure with array
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 array(1) {
   ["sum"]=>
   int(42)
 }
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 array(1) {
   ["sum"]=>
-  int(43)
+  int(42)
 }
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 array(1) {
   ["sum"]=>
-  int(45)
+  int(42)
 }
 bool(true)
 End result:int(42)
@@ -139,14 +145,20 @@ bool(true)
 End result:int(48)
 
 closure with object
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 object(stdClass)#1 (1) {
   ["sum"]=>
   int(42)
 }
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 object(stdClass)#1 (1) {
   ["sum"]=>
   int(43)
 }
+
+Warning: {closure}(): Argument #3 ($udata) must be passed by reference, value given in %s on line %d
 object(stdClass)#1 (1) {
   ["sum"]=>
   int(45)
index f7530973eab32801fda998038463e08e0637824d..df4f6d352df3630685245098a64de8063bc0a88c 100644 (file)
@@ -6,8 +6,8 @@ class p {
    public $x;
    function __construct($x){$this->x=$x;}
 }
-function a(&$a, &$b){var_dump(__FUNCTION__);return $a->x - $b->x;}
-function b(&$a, &$b){var_dump(__FUNCTION__);return $a->x - $b->x;}
+function a($a, $b){var_dump(__FUNCTION__);return $a->x - $b->x;}
+function b($a, $b){var_dump(__FUNCTION__);return $a->x - $b->x;}
 
 $p1 = array(new p(2), new p(1), new p(0));
 $p2 = array(new p(0), new p(2), new p(3));
index 3ac975694185c3c914988da9f43a49a48cba3aa4..61600fa57843647c6935345fc7f808becd0e39dc 100644 (file)
@@ -34,6 +34,14 @@ echo "Done\n";
 ?>
 --EXPECTF--
 Notice: Only variables should be passed by reference in %s on line %d
+
+Warning: test(): Argument #3 ($columns) must be passed by reference, value given in %s on line %d
+
+Warning: test(): Argument #3 ($columns) must be passed by reference, value given in %s on line %d
+
+Warning: test(): Argument #3 ($columns) must be passed by reference, value given in %s on line %d
+
+Warning: test(): Argument #3 ($columns) must be passed by reference, value given in %s on line %d
 object(Test)#%d (4) {
   ["_table"]=>
   string(0) ""
index b3f0a311017d7b8716a169e31660c665c429075a..2cfeb734b493770c73e622fd2cec8684d7e3105d 100644 (file)
@@ -11,5 +11,8 @@ array_walk_recursive(
 );
 echo "Done";
 ?>
---EXPECT--
+--EXPECTF--
+Warning: {closure}(): Argument #3 ($userdata) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #3 ($userdata) must be passed by reference, value given in %s on line %d
 Done
index fd92a9f8561ce3c51eff8d4e15e24fee3f9425f1..ec3c6cdf397d7c7fce78e3422cb96c409e6e87bf 100644 (file)
@@ -34,7 +34,7 @@ var_dump($array_arg);
 
 echo "Done"
 ?>
---EXPECT--
+--EXPECTF--
 *** Testing uasort() : anonymous function as 'cmp_function' ***
 -- Anonymous 'cmp_function' with parameters passed by value --
 bool(true)
@@ -51,6 +51,22 @@ array(5) {
   int(100)
 }
 -- Anonymous 'cmp_function' with parameters passed by reference --
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
 bool(true)
 array(4) {
   ["a"]=>
diff --git a/ext/standard/tests/array/uasort_variation9.phpt b/ext/standard/tests/array/uasort_variation9.phpt
deleted file mode 100644 (file)
index 05e9803..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
---TEST--
-Test uasort() function : usage variations - 'cmp_function' with reference argument
---FILE--
-<?php
-/* Testing uasort() functionality with comparison function having arguments as reference
- */
-
-echo "*** Testing uasort() : 'cmp_function' with reference arguments ***\n";
-
-// comparison function
-function cmp(&$value1, &$value2)
-{
-  if($value1 == $value2) {
-    return 0;
-  }
-  else if($value1 > $value2) {
-    return 1;
-  }
-  else
-    return -1;
-}
-
-// Int array with default keys
-$int_values = array(1, 8, 9, 3, 2, 6, 7);
-echo "-- Passing integer values to 'cmp_function' --\n";
-var_dump( uasort($int_values, 'cmp') );
-var_dump($int_values);
-
-// String array with default keys
-$string_values = array("Mango", "Apple", "Orange", "Banana");
-echo "-- Passing string values to 'cmp_function' --\n";
-var_dump( uasort($string_values, 'cmp') );
-var_dump($string_values);
-
-echo "Done"
-?>
---EXPECT--
-*** Testing uasort() : 'cmp_function' with reference arguments ***
--- Passing integer values to 'cmp_function' --
-bool(true)
-array(7) {
-  [0]=>
-  int(1)
-  [4]=>
-  int(2)
-  [3]=>
-  int(3)
-  [5]=>
-  int(6)
-  [6]=>
-  int(7)
-  [1]=>
-  int(8)
-  [2]=>
-  int(9)
-}
--- Passing string values to 'cmp_function' --
-bool(true)
-array(4) {
-  [1]=>
-  string(5) "Apple"
-  [3]=>
-  string(6) "Banana"
-  [0]=>
-  string(5) "Mango"
-  [2]=>
-  string(6) "Orange"
-}
-Done
index aa814245de8357613a5a69057533ebbaeb7de242..02e2cac7f22bcd8b583f1411f2dcb52b5f7189c5 100644 (file)
@@ -32,7 +32,7 @@ echo "\n-- Anonymous 'cmp_function' with parameters passed by reference --\n";
 var_dump( usort($array_arg, $cmp_function) );
 var_dump($array_arg);
 ?>
---EXPECT--
+--EXPECTF--
 *** Testing usort() : usage variation ***
 
 -- Anonymous 'cmp_function' with parameters passed by value --
@@ -51,6 +51,22 @@ array(5) {
 }
 
 -- Anonymous 'cmp_function' with parameters passed by reference --
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #1 ($value1) must be passed by reference, value given in %s on line %d
+
+Warning: {closure}(): Argument #2 ($value2) must be passed by reference, value given in %s on line %d
 bool(true)
 array(4) {
   [0]=>