]> granicus.if.org Git - php/commitdiff
Argument unpacking with Traversables and non-integer keys.
authorDmitry Stogov <dmitry@zend.com>
Wed, 4 Jul 2018 19:34:36 +0000 (22:34 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 4 Jul 2018 19:34:36 +0000 (22:34 +0300)
Changed error message, added UPGRADING note and test.

UPGRADING
Zend/tests/arg_unpack/non_integer_keys.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index f616bf9cda308e39087ca7ff33dc4e24aaaa7675..e926cd18cfc8670d769dd97902b49caee13fbda6 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -80,6 +80,19 @@ Core:
     note that reading and writing a value inside a single expression remains
     undefined behavior and may change again in the future.
 
+  . Argument unpacking stopped working with Traversables with non-integer keys.
+    The following code worked in PHP 7.0-7.2 by accident.
+
+        function foo(...$args) {
+            var_dump($args);
+        }
+        function gen() {
+            yield 1.23 => 123;
+        }
+        foo(...gen());
+
+    Now it generates an exception.
+
 BCMath:
   . All warnings thrown by BCMath functions are now using PHP's error handling.
     Formerly some warnings have directly been written to stderr.
diff --git a/Zend/tests/arg_unpack/non_integer_keys.phpt b/Zend/tests/arg_unpack/non_integer_keys.phpt
new file mode 100644 (file)
index 0000000..19ed61f
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Argument unpacking does not work with non-integer keys
+--FILE--
+<?php
+function foo(...$args) {
+       var_dump($args);
+}
+function gen() {
+       yield 1.23 => 123;
+       yield "2.34" => 234;
+}
+
+try {
+       foo(...gen());
+} catch (Error $ex) {
+       echo "Exception: " . $ex->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+Exception: Cannot unpack Traversable with non-integer keys
index c5ff50cf852d667cacd4c4ce7c01635b5b598349..5fb94b142ec988600866fb12fa95ed3c677354c3 100644 (file)
@@ -4522,10 +4522,11 @@ ZEND_VM_C_LABEL(send_again):
                                        }
 
                                        if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) {
-                                               ZEND_ASSERT(Z_TYPE(key) == IS_STRING);
                                                zend_throw_error(NULL,
-                                                       "Cannot unpack Traversable with string keys");
-                                               zval_ptr_dtor_str(&key);
+                                                       (Z_TYPE(key) == IS_STRING) ?
+                                                               "Cannot unpack Traversable with string keys" :
+                                                               "Cannot unpack Traversable with non-integer keys");
+                                               zval_ptr_dtor(&key);
                                                break;
                                        }
                                }
index 2724bca69ce2f63b957f0a88563cfb9445ea2cd6..7aeb0a7d39cf389d7b03d7c460498bac00f06f44 100644 (file)
@@ -1359,10 +1359,11 @@ send_again:
                                        }
 
                                        if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) {
-                                               ZEND_ASSERT(Z_TYPE(key) == IS_STRING);
                                                zend_throw_error(NULL,
-                                                       "Cannot unpack Traversable with string keys");
-                                               zval_ptr_dtor_str(&key);
+                                                       (Z_TYPE(key) == IS_STRING) ?
+                                                               "Cannot unpack Traversable with string keys" :
+                                                               "Cannot unpack Traversable with non-integer keys");
+                                               zval_ptr_dtor(&key);
                                                break;
                                        }
                                }