@@ -446,6 +446,32 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
446
446
return SUCCESS ;
447
447
}
448
448
449
+ static int zend_ast_add_unpacked_element (zval * result , zval * expr ) {
450
+ if (EXPECTED (Z_TYPE_P (expr ) == IS_ARRAY )) {
451
+ HashTable * ht = Z_ARRVAL_P (expr );
452
+ zval * val ;
453
+ zend_string * key ;
454
+
455
+ ZEND_HASH_FOREACH_STR_KEY_VAL (ht , key , val ) {
456
+ if (key ) {
457
+ zend_throw_error (NULL , "Cannot unpack array with string keys" );
458
+ return FAILURE ;
459
+ } else {
460
+ if (!zend_hash_next_index_insert (Z_ARRVAL_P (result ), val )) {
461
+ zend_error (E_WARNING , "Cannot add element to the array as the next element is already occupied" );
462
+ break ;
463
+ }
464
+ Z_TRY_ADDREF_P (val );
465
+ }
466
+ } ZEND_HASH_FOREACH_END ();
467
+ return SUCCESS ;
468
+ }
469
+
470
+ /* Objects or references cannot occur in a constant expression. */
471
+ zend_throw_error (NULL , "Only arrays and Traversables can be unpacked" );
472
+ return FAILURE ;
473
+ }
474
+
449
475
ZEND_API int ZEND_FASTCALL zend_ast_evaluate (zval * result , zend_ast * ast , zend_class_entry * scope )
450
476
{
451
477
zval op1 , op2 ;
@@ -642,6 +668,19 @@ ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_c
642
668
array_init (result );
643
669
for (i = 0 ; i < list -> children ; i ++ ) {
644
670
zend_ast * elem = list -> child [i ];
671
+ if (elem -> kind == ZEND_AST_UNPACK ) {
672
+ if (UNEXPECTED (zend_ast_evaluate (& op1 , elem -> child [0 ], scope ) != SUCCESS )) {
673
+ zval_ptr_dtor_nogc (result );
674
+ return FAILURE ;
675
+ }
676
+ if (UNEXPECTED (zend_ast_add_unpacked_element (result , & op1 ) != SUCCESS )) {
677
+ zval_ptr_dtor_nogc (& op1 );
678
+ zval_ptr_dtor_nogc (result );
679
+ return FAILURE ;
680
+ }
681
+ zval_ptr_dtor_nogc (& op1 );
682
+ continue ;
683
+ }
645
684
if (elem -> child [1 ]) {
646
685
if (UNEXPECTED (zend_ast_evaluate (& op1 , elem -> child [1 ], scope ) != SUCCESS )) {
647
686
zval_ptr_dtor_nogc (result );
0 commit comments