31
31
32
32
#include "zend.h"
33
33
#include "zend_API.h"
34
+ #include "zend_language_scanner.h"
35
+ #include "zend_language_scanner_defs.h"
36
+ #include "zend_language_parser.h"
34
37
#include "zend_exceptions.h"
35
38
#include "zend_operators.h"
36
39
#include "zend_constants.h"
@@ -149,6 +152,8 @@ typedef struct {
149
152
zend_object zo ;
150
153
} reflection_object ;
151
154
155
+ static int _reflection_param_get_default_arg_info (zend_internal_arg_info * arg_info , zval * default_value_zval );
156
+
152
157
static inline reflection_object * reflection_object_from_obj (zend_object * obj ) {
153
158
return (reflection_object * )((char * )(obj ) - XtOffsetOf (reflection_object , zo ));
154
159
}
@@ -571,6 +576,31 @@ static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
571
576
}
572
577
/* }}} */
573
578
579
+ static void append_parameter_default_value (smart_str * str , zval zv )
580
+ {
581
+ if (Z_TYPE (zv ) == IS_TRUE ) {
582
+ smart_str_appends (str , "true" );
583
+ } else if (Z_TYPE (zv ) == IS_FALSE ) {
584
+ smart_str_appends (str , "false" );
585
+ } else if (Z_TYPE (zv ) == IS_NULL ) {
586
+ smart_str_appends (str , "NULL" );
587
+ } else if (Z_TYPE (zv ) == IS_STRING ) {
588
+ smart_str_appendc (str , '\'' );
589
+ smart_str_appendl (str , Z_STRVAL (zv ), MIN (Z_STRLEN (zv ), 15 ));
590
+ if (Z_STRLEN (zv ) > 15 ) {
591
+ smart_str_appends (str , "..." );
592
+ }
593
+ smart_str_appendc (str , '\'' );
594
+ } else if (Z_TYPE (zv ) == IS_ARRAY ) {
595
+ smart_str_appends (str , "Array" );
596
+ } else {
597
+ zend_string * tmp_zv_str ;
598
+ zend_string * zv_str = zval_get_tmp_string (& zv , & tmp_zv_str );
599
+ smart_str_append (str , zv_str );
600
+ zend_tmp_string_release (tmp_zv_str );
601
+ }
602
+ }
603
+
574
604
/* {{{ _parameter_string */
575
605
static void _parameter_string (smart_str * str , zend_function * fptr , struct _zend_arg_info * arg_info , uint32_t offset , zend_bool required , char * indent )
576
606
{
@@ -600,39 +630,38 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_
600
630
} else {
601
631
smart_str_append_printf (str , "$param%d" , offset );
602
632
}
603
- if (fptr -> type == ZEND_USER_FUNCTION && !required ) {
604
- zend_op * precv = _get_recv_op ((zend_op_array * )fptr , offset );
605
- if (precv && precv -> opcode == ZEND_RECV_INIT && precv -> op2_type != IS_UNUSED ) {
606
- zval zv ;
633
+ if (!required ) {
634
+ zval zv ;
607
635
608
- smart_str_appends (str , " = " );
609
- ZVAL_COPY (& zv , RT_CONSTANT (precv , precv -> op2 ));
610
- if (UNEXPECTED (zval_update_constant_ex (& zv , fptr -> common .scope ) == FAILURE )) {
611
- zval_ptr_dtor (& zv );
612
- return ;
636
+ if (fptr -> type == ZEND_USER_FUNCTION ) {
637
+ zend_op * precv = _get_recv_op ((zend_op_array * )fptr , offset );
638
+ if (precv && precv -> opcode == ZEND_RECV_INIT && precv -> op2_type != IS_UNUSED ) {
639
+ ZVAL_COPY (& zv , RT_CONSTANT (precv , precv -> op2 ));
640
+ if (UNEXPECTED (zval_update_constant_ex (& zv , fptr -> common .scope ) == FAILURE )) {
641
+ zval_ptr_dtor (& zv );
642
+ return ;
643
+ }
644
+
645
+ smart_str_appends (str , " = " );
646
+ append_parameter_default_value (str , zv );
647
+ zval_ptr_dtor (& zv );
613
648
}
614
- if (Z_TYPE (zv ) == IS_TRUE ) {
615
- smart_str_appends (str , "true" );
616
- } else if (Z_TYPE (zv ) == IS_FALSE ) {
617
- smart_str_appends (str , "false" );
618
- } else if (Z_TYPE (zv ) == IS_NULL ) {
619
- smart_str_appends (str , "NULL" );
620
- } else if (Z_TYPE (zv ) == IS_STRING ) {
621
- smart_str_appendc (str , '\'' );
622
- smart_str_appendl (str , Z_STRVAL (zv ), MIN (Z_STRLEN (zv ), 15 ));
623
- if (Z_STRLEN (zv ) > 15 ) {
624
- smart_str_appends (str , "..." );
649
+ } else {
650
+ if (((zend_internal_arg_info * ) arg_info )-> default_value != NULL ) {
651
+ if (_reflection_param_get_default_arg_info ((zend_internal_arg_info * ) arg_info , & zv ) == FAILURE ) {
652
+ zval_ptr_dtor (& zv );
653
+ return ;
625
654
}
626
- smart_str_appendc (str , '\'' );
627
- } else if (Z_TYPE (zv ) == IS_ARRAY ) {
628
- smart_str_appends (str , "Array" );
629
- } else {
630
- zend_string * tmp_zv_str ;
631
- zend_string * zv_str = zval_get_tmp_string (& zv , & tmp_zv_str );
632
- smart_str_append (str , zv_str );
633
- zend_tmp_string_release (tmp_zv_str );
655
+
656
+ if (UNEXPECTED (zval_update_constant_ex (& zv , fptr -> common .scope ) == FAILURE )) {
657
+ zval_ptr_dtor (& zv );
658
+ return ;
659
+ }
660
+
661
+ smart_str_appends (str , " = " );
662
+ append_parameter_default_value (str , zv );
663
+ zval_ptr_dtor (& zv );
634
664
}
635
- zval_ptr_dtor (& zv );
636
665
}
637
666
}
638
667
smart_str_appends (str , " ]" );
@@ -1351,10 +1380,6 @@ static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTIO
1351
1380
}
1352
1381
1353
1382
param = intern -> ptr ;
1354
- if (param -> fptr -> type != ZEND_USER_FUNCTION ) {
1355
- zend_throw_exception_ex (reflection_exception_ptr , 0 , "Cannot determine default value for internal functions" );
1356
- return NULL ;
1357
- }
1358
1383
1359
1384
return param ;
1360
1385
}
@@ -1379,6 +1404,82 @@ static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS
1379
1404
}
1380
1405
/* }}} */
1381
1406
1407
+ /* {{{ _reflection_param_get_default_arg_info */
1408
+ static int _reflection_param_get_default_arg_info (zend_internal_arg_info * arg_info , zval * default_value_zval )
1409
+ {
1410
+ const char * default_value = arg_info -> default_value ;
1411
+ if (default_value == NULL ) {
1412
+ zend_throw_exception_ex (reflection_exception_ptr , 0 , "Internal error: Failed to retrieve the default value" );
1413
+ return FAILURE ;
1414
+ }
1415
+
1416
+ zval code_zv ;
1417
+ zend_bool original_in_compilation ;
1418
+ uint32_t original_compiler_options ;
1419
+ zend_lex_state original_lex_state ;
1420
+ zend_ast * ast ;
1421
+ zend_arena * ast_arena ;
1422
+ int success = FAILURE ;
1423
+
1424
+ size_t str1_length = strlen ("<?php " );
1425
+ size_t str2_length = strlen (default_value );
1426
+ size_t str3_length = strlen (";" );
1427
+ size_t len = str1_length + str2_length + str3_length ;
1428
+ zend_string * code = zend_string_alloc (len , 0 );
1429
+
1430
+ memcpy (ZSTR_VAL (code ), "<?php " , str1_length );
1431
+ memcpy (ZSTR_VAL (code ) + str1_length , default_value , str2_length );
1432
+ memcpy (ZSTR_VAL (code ) + str1_length + str2_length , ";" , str3_length );
1433
+ ZSTR_VAL (code )[len ] = '\0' ;
1434
+ ZVAL_STR_COPY (& code_zv , code );
1435
+
1436
+ original_in_compilation = CG (in_compilation );
1437
+ original_compiler_options = CG (compiler_options );
1438
+ zend_save_lexical_state (& original_lex_state );
1439
+
1440
+ CG (in_compilation ) = 1 ;
1441
+ CG (compiler_options ) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION ;
1442
+
1443
+ if (zend_prepare_string_for_scanning (& code_zv , "" ) == SUCCESS ) {
1444
+ CG (ast ) = NULL ;
1445
+ CG (ast_arena ) = zend_arena_create (1024 * 32 );
1446
+ LANG_SCNG (yy_state ) = yycINITIAL ;
1447
+
1448
+ if (zendparse () != 0 ) {
1449
+ zend_ast_destroy (CG (ast ));
1450
+ zend_arena_destroy (CG (ast_arena ));
1451
+ CG (ast ) = NULL ;
1452
+ }
1453
+ }
1454
+
1455
+ ast = CG (ast );
1456
+ ast_arena = CG (ast_arena );
1457
+
1458
+ if (ast ) {
1459
+ zend_ast_list * statement_list = zend_ast_get_list (ast );
1460
+ zend_ast * const_expression_ast = statement_list -> child [0 ];
1461
+ if (const_expression_ast ) {
1462
+ zend_const_expr_to_zval (default_value_zval , const_expression_ast );
1463
+ success = SUCCESS ;
1464
+ }
1465
+ }
1466
+
1467
+ zend_restore_lexical_state (& original_lex_state );
1468
+ CG (compiler_options ) = original_compiler_options ;
1469
+ CG (in_compilation ) = original_in_compilation ;
1470
+
1471
+ zval_dtor (& code_zv );
1472
+ zend_string_free (code );
1473
+ zend_ast_destroy (ast );
1474
+ zend_arena_destroy (ast_arena );
1475
+
1476
+ if (success == FAILURE ) {
1477
+ zend_throw_exception_ex (reflection_exception_ptr , 0 , "Internal error: Failed to retrieve the default value" );
1478
+ }
1479
+
1480
+ return success ;
1481
+ }
1482
+
1382
1483
/* {{{ Preventing __clone from being called */
1383
1484
ZEND_METHOD (reflection , __clone )
1384
1485
{
@@ -2667,22 +2768,24 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2667
2768
{
2668
2769
reflection_object * intern ;
2669
2770
parameter_reference * param ;
2670
- zend_op * precv ;
2671
2771
2672
2772
if (zend_parse_parameters_none () == FAILURE ) {
2673
2773
return ;
2674
2774
}
2675
2775
GET_REFLECTION_OBJECT_PTR (param );
2676
2776
2677
- if (param -> fptr -> type != ZEND_USER_FUNCTION )
2777
+ if (param -> fptr -> type == ZEND_USER_FUNCTION )
2778
+ {
2779
+ zend_op * precv ;
2780
+ precv = _get_recv_op ((zend_op_array * )param -> fptr , param -> offset );
2781
+ if (!precv || precv -> opcode != ZEND_RECV_INIT || precv -> op2_type == IS_UNUSED ) {
2782
+ RETURN_FALSE ;
2783
+ }
2784
+ } else if (((zend_internal_arg_info * ) param -> arg_info )-> default_value == NULL )
2678
2785
{
2679
2786
RETURN_FALSE ;
2680
2787
}
2681
2788
2682
- precv = _get_recv_op ((zend_op_array * )param -> fptr , param -> offset );
2683
- if (!precv || precv -> opcode != ZEND_RECV_INIT || precv -> op2_type == IS_UNUSED ) {
2684
- RETURN_FALSE ;
2685
- }
2686
2789
RETURN_TRUE ;
2687
2790
}
2688
2791
/* }}} */
@@ -2692,7 +2795,6 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2692
2795
ZEND_METHOD (reflection_parameter , getDefaultValue )
2693
2796
{
2694
2797
parameter_reference * param ;
2695
- zend_op * precv ;
2696
2798
2697
2799
if (zend_parse_parameters_none () == FAILURE ) {
2698
2800
return ;
@@ -2703,14 +2805,29 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
2703
2805
return ;
2704
2806
}
2705
2807
2706
- precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2707
- if (!precv ) {
2708
- return ;
2709
- }
2808
+ if (param -> fptr -> type == ZEND_USER_FUNCTION ) {
2809
+ zend_op * precv ;
2810
+ precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2811
+ if (!precv ) {
2812
+ return ;
2813
+ }
2710
2814
2711
- ZVAL_COPY (return_value , RT_CONSTANT (precv , precv -> op2 ));
2712
- if (Z_TYPE_P (return_value ) == IS_CONSTANT_AST ) {
2713
- zval_update_constant_ex (return_value , param -> fptr -> common .scope );
2815
+ ZVAL_COPY (return_value , RT_CONSTANT (precv , precv -> op2 ));
2816
+ if (Z_TYPE_P (return_value ) == IS_CONSTANT_AST ) {
2817
+ zval_update_constant_ex (return_value , param -> fptr -> common .scope );
2818
+ }
2819
+ } else {
2820
+ zval default_value_zval ;
2821
+ if (_reflection_param_get_default_arg_info ((zend_internal_arg_info * ) param -> arg_info , & default_value_zval ) == FAILURE ) {
2822
+ return ;
2823
+ }
2824
+
2825
+ ZVAL_COPY (return_value , & default_value_zval );
2826
+ if (Z_TYPE_P (return_value ) == IS_CONSTANT_AST ) {
2827
+ zval_update_constant_ex (return_value , param -> fptr -> common .scope );
2828
+ }
2829
+
2830
+ zval_dtor (& default_value_zval );
2714
2831
}
2715
2832
}
2716
2833
/* }}} */
@@ -2719,7 +2836,6 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
2719
2836
Returns whether the default value of this parameter is constant */
2720
2837
ZEND_METHOD (reflection_parameter , isDefaultValueConstant )
2721
2838
{
2722
- zend_op * precv ;
2723
2839
parameter_reference * param ;
2724
2840
2725
2841
if (zend_parse_parameters_none () == FAILURE ) {
@@ -2731,14 +2847,33 @@ ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2731
2847
RETURN_FALSE ;
2732
2848
}
2733
2849
2734
- precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2735
- if (precv && Z_TYPE_P (RT_CONSTANT (precv , precv -> op2 )) == IS_CONSTANT_AST ) {
2736
- zend_ast * ast = Z_ASTVAL_P (RT_CONSTANT (precv , precv -> op2 ));
2850
+ if (param -> fptr -> type == ZEND_USER_FUNCTION ) {
2851
+ zend_op * precv ;
2852
+ precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2853
+ if (precv && Z_TYPE_P (RT_CONSTANT (precv , precv -> op2 )) == IS_CONSTANT_AST ) {
2854
+ zend_ast * ast = NULL ;
2855
+ ast = Z_ASTVAL_P (RT_CONSTANT (precv , precv -> op2 ));
2856
+
2857
+ if (ast -> kind == ZEND_AST_CONSTANT || ast -> kind == ZEND_AST_CONSTANT_CLASS ) {
2858
+ zend_ast_destroy (ast );
2859
+ RETURN_TRUE ;
2860
+ }
2861
+ }
2862
+ } else {
2863
+ zval default_value_zval ;
2864
+ if (_reflection_param_get_default_arg_info ((zend_internal_arg_info * ) param -> arg_info , & default_value_zval ) == FAILURE ) {
2865
+ return ;
2866
+ }
2737
2867
2738
- if (ast -> kind == ZEND_AST_CONSTANT
2739
- || ast -> kind == ZEND_AST_CONSTANT_CLASS ) {
2740
- RETURN_TRUE ;
2868
+ if (Z_TYPE (default_value_zval ) == IS_CONSTANT_AST ) {
2869
+ zend_ast * ast = Z_ASTVAL (default_value_zval );
2870
+ if (ast -> kind == ZEND_AST_CONSTANT ) {
2871
+ zval_dtor (& default_value_zval );
2872
+ RETURN_TRUE ;
2873
+ }
2741
2874
}
2875
+
2876
+ zval_dtor (& default_value_zval );
2742
2877
}
2743
2878
2744
2879
RETURN_FALSE ;
@@ -2749,7 +2884,6 @@ ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2749
2884
Returns the default value's constant name if default value is constant or null */
2750
2885
ZEND_METHOD (reflection_parameter , getDefaultValueConstantName )
2751
2886
{
2752
- zend_op * precv ;
2753
2887
parameter_reference * param ;
2754
2888
2755
2889
if (zend_parse_parameters_none () == FAILURE ) {
@@ -2761,14 +2895,38 @@ ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
2761
2895
return ;
2762
2896
}
2763
2897
2764
- precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2765
- if (precv && Z_TYPE_P (RT_CONSTANT (precv , precv -> op2 )) == IS_CONSTANT_AST ) {
2766
- zend_ast * ast = Z_ASTVAL_P (RT_CONSTANT (precv , precv -> op2 ));
2898
+ if (param -> fptr -> type == ZEND_USER_FUNCTION ) {
2899
+ zend_op * precv ;
2900
+ precv = _reflection_param_get_default_precv (INTERNAL_FUNCTION_PARAM_PASSTHRU , param );
2901
+ if (precv && Z_TYPE_P (RT_CONSTANT (precv , precv -> op2 )) == IS_CONSTANT_AST ) {
2902
+ zend_ast * ast = Z_ASTVAL_P (RT_CONSTANT (precv , precv -> op2 ));
2903
+
2904
+ if (ast -> kind == ZEND_AST_CONSTANT ) {
2905
+ RETURN_STR_COPY (zend_ast_get_constant_name (ast ));
2906
+ } else if (ast -> kind == ZEND_AST_CONSTANT_CLASS ) {
2907
+ RETURN_STRINGL ("__CLASS__" , sizeof ("__CLASS__" )- 1 );
2908
+ }
2909
+ }
2910
+ } else {
2911
+ zval default_value_zval ;
2912
+ if (_reflection_param_get_default_arg_info ((zend_internal_arg_info * ) param -> arg_info , & default_value_zval ) == FAILURE ) {
2913
+ return ;
2914
+ }
2915
+
2916
+ if (Z_TYPE (default_value_zval ) == IS_CONSTANT_AST ) {
2917
+ zend_ast * ast = Z_ASTVAL (default_value_zval );
2918
+ if (ast -> kind == ZEND_AST_CONSTANT ) {
2919
+ zend_string * name = zend_ast_get_constant_name (ast );
2920
+ zval_dtor (& default_value_zval );
2921
+ zend_ast_destroy (ast );
2922
+
2923
+ RETURN_STR_COPY (name );
2924
+ } else if (ast -> kind == ZEND_AST_CONSTANT_CLASS ) {
2925
+ zval_dtor (& default_value_zval );
2926
+ zend_ast_destroy (ast );
2767
2927
2768
- if (ast -> kind == ZEND_AST_CONSTANT ) {
2769
- RETURN_STR_COPY (zend_ast_get_constant_name (ast ));
2770
- } else if (ast -> kind == ZEND_AST_CONSTANT_CLASS ) {
2771
- RETURN_STRINGL ("__CLASS__" , sizeof ("__CLASS__" )- 1 );
2928
+ RETURN_STRINGL ("__CLASS__" , sizeof ("__CLASS__" )- 1 );
2929
+ }
2772
2930
}
2773
2931
}
2774
2932
}
@@ -4281,7 +4439,7 @@ ZEND_METHOD(reflection_class, getProperties)
4281
4439
if (zend_parse_parameters (ZEND_NUM_ARGS (), "|l!" , & filter , & filter_is_null ) == FAILURE ) {
4282
4440
return ;
4283
4441
}
4284
-
4442
+
4285
4443
if (filter_is_null ) {
4286
4444
filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC ;
4287
4445
}
0 commit comments