@@ -498,17 +498,17 @@ zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
498
498
return zend_fetch_class_with_scope (zend_ast_get_str (ast ), (ast -> attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT ) | ZEND_FETCH_CLASS_EXCEPTION , scope );
499
499
}
500
500
501
- static zend_result ZEND_FASTCALL zend_ast_evaluate_ex (zval * result , zend_ast * ast , zend_class_entry * scope , bool * short_circuited_ptr )
501
+ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex (zval * result , zend_ast * ast , zend_class_entry * scope , zend_ast_evaluate_ctx * ctx )
502
502
{
503
503
zval op1 , op2 ;
504
504
zend_result ret = SUCCESS ;
505
- * short_circuited_ptr = false;
505
+ ctx -> short_circuited = false;
506
506
507
507
switch (ast -> kind ) {
508
508
case ZEND_AST_BINARY_OP :
509
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
509
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
510
510
ret = FAILURE ;
511
- } else if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
511
+ } else if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
512
512
zval_ptr_dtor_nogc (& op1 );
513
513
ret = FAILURE ;
514
514
} else {
@@ -520,9 +520,9 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
520
520
break ;
521
521
case ZEND_AST_GREATER :
522
522
case ZEND_AST_GREATER_EQUAL :
523
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
523
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
524
524
ret = FAILURE ;
525
- } else if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
525
+ } else if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
526
526
zval_ptr_dtor_nogc (& op1 );
527
527
ret = FAILURE ;
528
528
} else {
@@ -535,7 +535,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
535
535
}
536
536
break ;
537
537
case ZEND_AST_UNARY_OP :
538
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
538
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
539
539
ret = FAILURE ;
540
540
} else {
541
541
unary_op_type op = get_unary_op (ast -> attr );
@@ -588,12 +588,12 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
588
588
}
589
589
break ;
590
590
case ZEND_AST_AND :
591
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
591
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
592
592
ret = FAILURE ;
593
593
break ;
594
594
}
595
595
if (zend_is_true (& op1 )) {
596
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
596
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
597
597
zval_ptr_dtor_nogc (& op1 );
598
598
ret = FAILURE ;
599
599
break ;
@@ -606,14 +606,14 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
606
606
zval_ptr_dtor_nogc (& op1 );
607
607
break ;
608
608
case ZEND_AST_OR :
609
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
609
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
610
610
ret = FAILURE ;
611
611
break ;
612
612
}
613
613
if (zend_is_true (& op1 )) {
614
614
ZVAL_TRUE (result );
615
615
} else {
616
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
616
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
617
617
zval_ptr_dtor_nogc (& op1 );
618
618
ret = FAILURE ;
619
619
break ;
@@ -624,23 +624,23 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
624
624
zval_ptr_dtor_nogc (& op1 );
625
625
break ;
626
626
case ZEND_AST_CONDITIONAL :
627
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
627
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
628
628
ret = FAILURE ;
629
629
break ;
630
630
}
631
631
if (zend_is_true (& op1 )) {
632
632
if (!ast -> child [1 ]) {
633
633
* result = op1 ;
634
634
} else {
635
- if (UNEXPECTED (zend_ast_evaluate (result , ast -> child [1 ], scope ) != SUCCESS )) {
635
+ if (UNEXPECTED (zend_ast_evaluate_ex (result , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
636
636
zval_ptr_dtor_nogc (& op1 );
637
637
ret = FAILURE ;
638
638
break ;
639
639
}
640
640
zval_ptr_dtor_nogc (& op1 );
641
641
}
642
642
} else {
643
- if (UNEXPECTED (zend_ast_evaluate (result , ast -> child [2 ], scope ) != SUCCESS )) {
643
+ if (UNEXPECTED (zend_ast_evaluate_ex (result , ast -> child [2 ], scope , ctx ) != SUCCESS )) {
644
644
zval_ptr_dtor_nogc (& op1 );
645
645
ret = FAILURE ;
646
646
break ;
@@ -649,14 +649,14 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
649
649
}
650
650
break ;
651
651
case ZEND_AST_COALESCE :
652
- if (UNEXPECTED (zend_ast_evaluate (& op1 , ast -> child [0 ], scope ) != SUCCESS )) {
652
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
653
653
ret = FAILURE ;
654
654
break ;
655
655
}
656
656
if (Z_TYPE (op1 ) > IS_NULL ) {
657
657
* result = op1 ;
658
658
} else {
659
- if (UNEXPECTED (zend_ast_evaluate (result , ast -> child [1 ], scope ) != SUCCESS )) {
659
+ if (UNEXPECTED (zend_ast_evaluate_ex (result , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
660
660
zval_ptr_dtor_nogc (& op1 );
661
661
ret = FAILURE ;
662
662
break ;
@@ -665,7 +665,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
665
665
}
666
666
break ;
667
667
case ZEND_AST_UNARY_PLUS :
668
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [0 ], scope ) != SUCCESS )) {
668
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
669
669
ret = FAILURE ;
670
670
} else {
671
671
ZVAL_LONG (& op1 , 0 );
@@ -674,7 +674,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
674
674
}
675
675
break ;
676
676
case ZEND_AST_UNARY_MINUS :
677
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [0 ], scope ) != SUCCESS )) {
677
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
678
678
ret = FAILURE ;
679
679
} else {
680
680
ZVAL_LONG (& op1 , 0 );
@@ -695,7 +695,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
695
695
for (i = 0 ; i < list -> children ; i ++ ) {
696
696
zend_ast * elem = list -> child [i ];
697
697
if (elem -> kind == ZEND_AST_UNPACK ) {
698
- if (UNEXPECTED (zend_ast_evaluate (& op1 , elem -> child [0 ], scope ) != SUCCESS )) {
698
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , elem -> child [0 ], scope , ctx ) != SUCCESS )) {
699
699
zval_ptr_dtor_nogc (result );
700
700
return FAILURE ;
701
701
}
@@ -708,14 +708,14 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
708
708
continue ;
709
709
}
710
710
if (elem -> child [1 ]) {
711
- if (UNEXPECTED (zend_ast_evaluate (& op1 , elem -> child [1 ], scope ) != SUCCESS )) {
711
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , elem -> child [1 ], scope , ctx ) != SUCCESS )) {
712
712
zval_ptr_dtor_nogc (result );
713
713
return FAILURE ;
714
714
}
715
715
} else {
716
716
ZVAL_UNDEF (& op1 );
717
717
}
718
- if (UNEXPECTED (zend_ast_evaluate (& op2 , elem -> child [0 ], scope ) != SUCCESS )) {
718
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , elem -> child [0 ], scope , ctx ) != SUCCESS )) {
719
719
zval_ptr_dtor_nogc (& op1 );
720
720
zval_ptr_dtor_nogc (result );
721
721
return FAILURE ;
@@ -734,13 +734,11 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
734
734
zend_error_noreturn (E_COMPILE_ERROR , "Cannot use [] for reading" );
735
735
}
736
736
737
- bool short_circuited ;
738
- if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , & short_circuited ) != SUCCESS )) {
737
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
739
738
ret = FAILURE ;
740
739
break ;
741
740
}
742
- if (short_circuited ) {
743
- * short_circuited_ptr = true;
741
+ if (ctx -> short_circuited ) {
744
742
ZVAL_NULL (result );
745
743
return SUCCESS ;
746
744
}
@@ -753,7 +751,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
753
751
break ;
754
752
}
755
753
756
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
754
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
757
755
zval_ptr_dtor_nogc (& op1 );
758
756
ret = FAILURE ;
759
757
break ;
@@ -787,7 +785,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
787
785
zval case_value_zv ;
788
786
ZVAL_UNDEF (& case_value_zv );
789
787
if (case_value_ast != NULL ) {
790
- if (UNEXPECTED (zend_ast_evaluate (& case_value_zv , case_value_ast , scope ) != SUCCESS )) {
788
+ if (UNEXPECTED (zend_ast_evaluate_ex (& case_value_zv , case_value_ast , scope , ctx ) != SUCCESS )) {
791
789
return FAILURE ;
792
790
}
793
791
}
@@ -834,6 +832,9 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
834
832
return FAILURE ;
835
833
}
836
834
835
+ /* Even if there is no constructor, the object can have cause side-effects in various ways (__toString(), __get(), __isset(), etc). */
836
+ ctx -> had_side_effects = true;
837
+
837
838
zend_ast_list * args_ast = zend_ast_get_list (ast -> child [1 ]);
838
839
if (args_ast -> attr ) {
839
840
/* Has named arguments. */
@@ -846,7 +847,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
846
847
name = zend_ast_get_str (arg_ast -> child [0 ]);
847
848
arg_ast = arg_ast -> child [1 ];
848
849
}
849
- if (zend_ast_evaluate (& arg , arg_ast , scope ) == FAILURE ) {
850
+ if (zend_ast_evaluate_ex (& arg , arg_ast , scope , ctx ) == FAILURE ) {
850
851
zend_array_destroy (args );
851
852
zval_ptr_dtor (result );
852
853
return FAILURE ;
@@ -876,7 +877,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
876
877
ALLOCA_FLAG (use_heap )
877
878
zval * args = do_alloca (sizeof (zval ) * args_ast -> children , use_heap );
878
879
for (uint32_t i = 0 ; i < args_ast -> children ; i ++ ) {
879
- if (zend_ast_evaluate (& args [i ], args_ast -> child [i ], scope ) == FAILURE ) {
880
+ if (zend_ast_evaluate_ex (& args [i ], args_ast -> child [i ], scope , ctx ) == FAILURE ) {
880
881
for (uint32_t j = 0 ; j < i ; j ++ ) {
881
882
zval_ptr_dtor (& args [j ]);
882
883
}
@@ -908,22 +909,20 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
908
909
case ZEND_AST_PROP :
909
910
case ZEND_AST_NULLSAFE_PROP :
910
911
{
911
- bool short_circuited ;
912
- if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , & short_circuited ) != SUCCESS )) {
912
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op1 , ast -> child [0 ], scope , ctx ) != SUCCESS )) {
913
913
return FAILURE ;
914
914
}
915
- if (short_circuited ) {
916
- * short_circuited_ptr = true;
915
+ if (ctx -> short_circuited ) {
917
916
ZVAL_NULL (result );
918
917
return SUCCESS ;
919
918
}
920
919
if (ast -> kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE (op1 ) == IS_NULL ) {
921
- * short_circuited_ptr = true;
920
+ ctx -> short_circuited = true;
922
921
ZVAL_NULL (result );
923
922
return SUCCESS ;
924
923
}
925
924
926
- if (UNEXPECTED (zend_ast_evaluate (& op2 , ast -> child [1 ], scope ) != SUCCESS )) {
925
+ if (UNEXPECTED (zend_ast_evaluate_ex (& op2 , ast -> child [1 ], scope , ctx ) != SUCCESS )) {
927
926
zval_ptr_dtor_nogc (& op1 );
928
927
return FAILURE ;
929
928
}
@@ -976,8 +975,8 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *as
976
975
977
976
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate (zval * result , zend_ast * ast , zend_class_entry * scope )
978
977
{
979
- bool short_circuited ;
980
- return zend_ast_evaluate_ex (result , ast , scope , & short_circuited );
978
+ zend_ast_evaluate_ctx ctx = { 0 } ;
979
+ return zend_ast_evaluate_ex (result , ast , scope , & ctx );
981
980
}
982
981
983
982
static size_t ZEND_FASTCALL zend_ast_tree_size (zend_ast * ast )
0 commit comments