@@ -781,253 +781,174 @@ static inline int ct_eval_array_key_exists(zval *result, zval *op1, zval *op2) {
781
781
return SUCCESS ;
782
782
}
783
783
784
- /* The functions chosen here are simple to implement and either likely to affect a branch,
785
- * or just happened to be commonly used with constant operands in WP (need to test other
786
- * applications as well, of course). */
787
- static inline int ct_eval_func_call (
788
- zval * result , zend_string * name , uint32_t num_args , zval * * args ) {
789
- uint32_t i ;
790
- zend_execute_data * execute_data , * prev_execute_data ;
791
- zend_function * func ;
792
- bool overflow ;
793
-
794
- if (num_args == 0 ) {
795
- if (zend_string_equals_literal (name , "php_sapi_name" )
796
- || zend_string_equals_literal (name , "imagetypes" )
797
- || zend_string_equals_literal (name , "phpversion" )) {
798
- /* pass */
799
- } else {
800
- return FAILURE ;
801
- }
802
- } else if (num_args == 1 ) {
803
- if (zend_string_equals_literal (name , "chr" )) {
804
- zend_long c ;
805
- if (Z_TYPE_P (args [0 ]) != IS_LONG ) {
806
- return FAILURE ;
807
- }
808
-
809
- c = Z_LVAL_P (args [0 ]) & 0xff ;
810
- ZVAL_CHAR (result , c );
811
- return SUCCESS ;
812
- } else if (zend_string_equals_literal (name , "count" )) {
813
- if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
814
- return FAILURE ;
815
- }
816
-
817
- ZVAL_LONG (result , zend_hash_num_elements (Z_ARRVAL_P (args [0 ])));
818
- return SUCCESS ;
819
- } else if (zend_string_equals_literal (name , "ini_get" )) {
820
- zend_ini_entry * ini_entry ;
821
-
822
- if (Z_TYPE_P (args [0 ]) != IS_STRING ) {
823
- return FAILURE ;
824
- }
825
-
826
- ini_entry = zend_hash_find_ptr (EG (ini_directives ), Z_STR_P (args [0 ]));
827
- if (!ini_entry ) {
828
- ZVAL_FALSE (result );
829
- } else if (ini_entry -> modifiable != ZEND_INI_SYSTEM ) {
830
- return FAILURE ;
831
- } else if (ini_entry -> value ) {
832
- ZVAL_STR_COPY (result , ini_entry -> value );
833
- } else {
834
- ZVAL_EMPTY_STRING (result );
835
- }
836
- return SUCCESS ;
837
- } else if (zend_string_equals_literal (name , "trim" )
838
- || zend_string_equals_literal (name , "rtrim" )
839
- || zend_string_equals_literal (name , "ltrim" )
840
- || zend_string_equals_literal (name , "str_split" )
841
- || zend_string_equals_literal (name , "preg_quote" )
842
- || zend_string_equals_literal (name , "base64_encode" )
843
- || zend_string_equals_literal (name , "base64_decode" )
844
- || zend_string_equals_literal (name , "urlencode" )
845
- || zend_string_equals_literal (name , "urldecode" )
846
- || zend_string_equals_literal (name , "rawurlencode" )
847
- || zend_string_equals_literal (name , "rawurldecode" )
848
- || zend_string_equals_literal (name , "php_uname" )) {
849
- if (Z_TYPE_P (args [0 ]) != IS_STRING ) {
850
- return FAILURE ;
851
- }
852
- /* pass */
853
- } else if (zend_string_equals_literal (name , "array_keys" )
854
- || zend_string_equals_literal (name , "array_values" )) {
855
- if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
856
- return FAILURE ;
857
- }
858
- /* pass */
859
- } else if (zend_string_equals_literal (name , "array_flip" )) {
784
+ static zend_bool can_ct_eval_func_call (zend_string * name , uint32_t num_args , zval * * args ) {
785
+ /* Functions that can be evaluated independently of what the arguments are.
786
+ * It's okay if these functions throw on invalid arguments, but they should not warn. */
787
+ if (false
788
+ || zend_string_equals_literal (name , "array_diff" )
789
+ || zend_string_equals_literal (name , "array_diff_assoc" )
790
+ || zend_string_equals_literal (name , "array_diff_key" )
791
+ || zend_string_equals_literal (name , "array_key_exists" )
792
+ || zend_string_equals_literal (name , "array_keys" )
793
+ || zend_string_equals_literal (name , "array_merge" )
794
+ || zend_string_equals_literal (name , "array_merge_recursive" )
795
+ || zend_string_equals_literal (name , "array_replace" )
796
+ || zend_string_equals_literal (name , "array_replace_recursive" )
797
+ || zend_string_equals_literal (name , "array_values" )
798
+ || zend_string_equals_literal (name , "base64_decode" )
799
+ || zend_string_equals_literal (name , "base64_encode" )
800
+ || zend_string_equals_literal (name , "imagetypes" )
801
+ || zend_string_equals_literal (name , "in_array" )
802
+ || zend_string_equals_literal (name , "ltrim" )
803
+ || zend_string_equals_literal (name , "php_sapi_name" )
804
+ || zend_string_equals_literal (name , "php_uname" )
805
+ || zend_string_equals_literal (name , "phpversion" )
806
+ || zend_string_equals_literal (name , "pow" )
807
+ || zend_string_equals_literal (name , "preg_quote" )
808
+ || zend_string_equals_literal (name , "rawurldecode" )
809
+ || zend_string_equals_literal (name , "rawurlencode" )
810
+ || zend_string_equals_literal (name , "rtrim" )
811
+ || zend_string_equals_literal (name , "serialize" )
812
+ || zend_string_equals_literal (name , "str_contains" )
813
+ || zend_string_equals_literal (name , "str_ends_with" )
814
+ || zend_string_equals_literal (name , "str_split" )
815
+ || zend_string_equals_literal (name , "str_split" )
816
+ || zend_string_equals_literal (name , "str_starts_with" )
817
+ || zend_string_equals_literal (name , "strpos" )
818
+ || zend_string_equals_literal (name , "substr" )
819
+ || zend_string_equals_literal (name , "trim" )
820
+ || zend_string_equals_literal (name , "urldecode" )
821
+ || zend_string_equals_literal (name , "urlencode" )
822
+ || zend_string_equals_literal (name , "version_compare" )
823
+ ) {
824
+ return true;
825
+ }
826
+
827
+ /* For the following functions we need to check arguments to prevent warnings during
828
+ * evaluation. */
829
+ if (num_args == 1 ) {
830
+ if (zend_string_equals_literal (name , "array_flip" )) {
860
831
zval * entry ;
861
832
862
833
if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
863
- return FAILURE ;
834
+ return false ;
864
835
}
865
836
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
837
+ /* Throws warning for non int/string values. */
866
838
if (Z_TYPE_P (entry ) != IS_LONG && Z_TYPE_P (entry ) != IS_STRING ) {
867
- return FAILURE ;
839
+ return false ;
868
840
}
869
841
} ZEND_HASH_FOREACH_END ();
870
- /* pass */
871
- } else if (zend_string_equals_literal (name , "implode" )) {
842
+ return true;
843
+ }
844
+ if (zend_string_equals_literal (name , "implode" )) {
872
845
zval * entry ;
873
846
874
847
if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
875
- return FAILURE ;
848
+ return false ;
876
849
}
877
850
878
851
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
852
+ /* May throw warning during conversion to string. */
879
853
if (Z_TYPE_P (entry ) > IS_STRING ) {
880
- return FAILURE ;
854
+ return false ;
881
855
}
882
856
} ZEND_HASH_FOREACH_END ();
883
- /* pass */
884
- } else if (zend_string_equals_literal (name , "serialize" )) {
885
- /* pass */
886
- } else {
887
- return FAILURE ;
857
+ return true;
888
858
}
889
- } else if (num_args == 2 ) {
890
- if (zend_string_equals_literal (name , "in_array" )) {
891
- if (Z_TYPE_P (args [1 ]) != IS_ARRAY ) {
892
- return FAILURE ;
893
- }
894
- /* pass */
895
- } else if (zend_string_equals_literal (name , "str_split" )) {
896
- if (Z_TYPE_P (args [0 ]) != IS_STRING
897
- || Z_TYPE_P (args [1 ]) != IS_LONG
898
- || Z_LVAL_P (args [1 ]) <= 0 ) {
899
- return FAILURE ;
900
- }
901
- /* pass */
902
- } else if (zend_string_equals_literal (name , "array_key_exists" )) {
903
- if (Z_TYPE_P (args [1 ]) != IS_ARRAY
904
- || (Z_TYPE_P (args [0 ]) != IS_LONG
905
- && Z_TYPE_P (args [0 ]) != IS_STRING
906
- && Z_TYPE_P (args [0 ]) != IS_NULL )) {
907
- return FAILURE ;
908
- }
909
- /* pass */
910
- } else if (zend_string_equals_literal (name , "trim" )
911
- || zend_string_equals_literal (name , "rtrim" )
912
- || zend_string_equals_literal (name , "ltrim" )
913
- || zend_string_equals_literal (name , "preg_quote" )) {
914
- if (Z_TYPE_P (args [0 ]) != IS_STRING
915
- || Z_TYPE_P (args [1 ]) != IS_STRING ) {
916
- return FAILURE ;
917
- }
918
- /* pass */
919
- } else if (zend_string_equals_literal (name , "str_repeat" )) {
920
- if (Z_TYPE_P (args [0 ]) != IS_STRING
921
- || Z_TYPE_P (args [1 ]) != IS_LONG
922
- || zend_safe_address (Z_STRLEN_P (args [0 ]), Z_LVAL_P (args [1 ]), 0 , & overflow ) > 64 * 1024
923
- || overflow ) {
924
- return FAILURE ;
925
- }
926
- /* pass */
927
- } else if (zend_string_equals_literal (name , "array_merge" )
928
- || zend_string_equals_literal (name , "array_replace" )
929
- || zend_string_equals_literal (name , "array_merge_recursive" )
930
- || zend_string_equals_literal (name , "array_replace_recursive" )
931
- || zend_string_equals_literal (name , "array_diff" )
932
- || zend_string_equals_literal (name , "array_diff_assoc" )
933
- || zend_string_equals_literal (name , "array_diff_key" )) {
934
- for (i = 0 ; i < num_args ; i ++ ) {
935
- if (Z_TYPE_P (args [i ]) != IS_ARRAY ) {
936
- return FAILURE ;
937
- }
938
- }
939
- /* pass */
859
+ return false;
860
+ }
861
+
862
+ if (num_args == 2 ) {
863
+ if (zend_string_equals_literal (name , "str_repeat" )) {
864
+ /* Avoid creating overly large strings at compile-time. */
865
+ bool overflow ;
866
+ return Z_TYPE_P (args [0 ]) == IS_STRING
867
+ && Z_TYPE_P (args [1 ]) == IS_LONG
868
+ && zend_safe_address (Z_STRLEN_P (args [0 ]), Z_LVAL_P (args [1 ]), 0 , & overflow ) < 64 * 1024
869
+ && !overflow ;
940
870
} else if (zend_string_equals_literal (name , "implode" )) {
941
871
zval * entry ;
942
872
943
873
if ((Z_TYPE_P (args [0 ]) != IS_STRING || Z_TYPE_P (args [1 ]) != IS_ARRAY )
944
874
&& (Z_TYPE_P (args [0 ]) != IS_ARRAY || Z_TYPE_P (args [1 ]) != IS_STRING )) {
945
- return FAILURE ;
875
+ return false ;
946
876
}
947
877
878
+ /* May throw warning during conversion to string. */
948
879
if (Z_TYPE_P (args [0 ]) == IS_ARRAY ) {
949
880
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
950
881
if (Z_TYPE_P (entry ) > IS_STRING ) {
951
- return FAILURE ;
882
+ return false ;
952
883
}
953
884
} ZEND_HASH_FOREACH_END ();
954
885
} else {
955
886
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [1 ]), entry ) {
956
887
if (Z_TYPE_P (entry ) > IS_STRING ) {
957
- return FAILURE ;
888
+ return false ;
958
889
}
959
890
} ZEND_HASH_FOREACH_END ();
960
891
}
961
- /* pass */
962
- } else if (zend_string_equals_literal (name , "strpos" )
963
- || zend_string_equals_literal (name , "str_contains" )
964
- || zend_string_equals_literal (name , "str_starts_with" )
965
- || zend_string_equals_literal (name , "str_ends_with" )
966
- || zend_string_equals_literal (name , "version_compare" )) {
967
- if (Z_TYPE_P (args [0 ]) != IS_STRING
968
- || Z_TYPE_P (args [1 ]) != IS_STRING ) {
969
- return FAILURE ;
970
- }
971
- /* pass */
972
- } else if (zend_string_equals_literal (name , "substr" )) {
973
- if (Z_TYPE_P (args [0 ]) != IS_STRING
974
- || Z_TYPE_P (args [1 ]) != IS_LONG ) {
975
- return FAILURE ;
976
- }
977
- /* pass */
978
- } else if (zend_string_equals_literal (name , "pow" )) {
979
- if ((Z_TYPE_P (args [0 ]) != IS_LONG && Z_TYPE_P (args [0 ]) != IS_DOUBLE )
980
- || (Z_TYPE_P (args [1 ]) != IS_LONG && Z_TYPE_P (args [1 ]) != IS_DOUBLE )) {
981
- return FAILURE ;
982
- }
983
- /* pass */
984
- } else {
985
- return FAILURE ;
892
+ return true;
986
893
}
987
- } else if (num_args == 3 ) {
988
- if (zend_string_equals_literal (name , "in_array" )) {
989
- if (Z_TYPE_P (args [1 ]) != IS_ARRAY
990
- || (Z_TYPE_P (args [2 ]) != IS_FALSE
991
- && Z_TYPE_P (args [2 ]) != IS_TRUE )) {
894
+ return false;
895
+ }
896
+
897
+ return false;
898
+ }
899
+
900
+ /* The functions chosen here are simple to implement and either likely to affect a branch,
901
+ * or just happened to be commonly used with constant operands in WP (need to test other
902
+ * applications as well, of course). */
903
+ static inline int ct_eval_func_call (
904
+ zval * result , zend_string * name , uint32_t num_args , zval * * args ) {
905
+ uint32_t i ;
906
+ zend_execute_data * execute_data , * prev_execute_data ;
907
+ zend_function * func = zend_hash_find_ptr (CG (function_table ), name );
908
+ if (!func || func -> type != ZEND_INTERNAL_FUNCTION ) {
909
+ return FAILURE ;
910
+ }
911
+
912
+ if (num_args == 1 ) {
913
+ /* Handle a few functions for which we manually implement evaluation here. */
914
+ if (zend_string_equals_literal (name , "chr" )) {
915
+ zend_long c ;
916
+ if (Z_TYPE_P (args [0 ]) != IS_LONG ) {
992
917
return FAILURE ;
993
918
}
994
- /* pass */
995
- } else if (zend_string_equals_literal (name , "array_merge" )
996
- || zend_string_equals_literal (name , "array_replace" )
997
- || zend_string_equals_literal (name , "array_merge_recursive" )
998
- || zend_string_equals_literal (name , "array_replace_recursive" )
999
- || zend_string_equals_literal (name , "array_diff" )
1000
- || zend_string_equals_literal (name , "array_diff_assoc" )
1001
- || zend_string_equals_literal (name , "array_diff_key" )) {
1002
- for (i = 0 ; i < num_args ; i ++ ) {
1003
- if (Z_TYPE_P (args [i ]) != IS_ARRAY ) {
1004
- return FAILURE ;
1005
- }
919
+
920
+ c = Z_LVAL_P (args [0 ]) & 0xff ;
921
+ ZVAL_CHAR (result , c );
922
+ return SUCCESS ;
923
+ } else if (zend_string_equals_literal (name , "count" )) {
924
+ if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
925
+ return FAILURE ;
1006
926
}
1007
- /* pass */
1008
- } else if (zend_string_equals_literal (name , "version_compare" )) {
1009
- if (Z_TYPE_P (args [0 ]) != IS_STRING
1010
- || Z_TYPE_P (args [1 ]) != IS_STRING
1011
- || Z_TYPE_P (args [2 ]) != IS_STRING ) {
927
+
928
+ ZVAL_LONG (result , zend_hash_num_elements (Z_ARRVAL_P (args [0 ])));
929
+ return SUCCESS ;
930
+ } else if (zend_string_equals_literal (name , "ini_get" )) {
931
+ zend_ini_entry * ini_entry ;
932
+
933
+ if (Z_TYPE_P (args [0 ]) != IS_STRING ) {
1012
934
return FAILURE ;
1013
935
}
1014
- /* pass */
1015
- } else if ( zend_string_equals_literal ( name , "substr" )) {
1016
- if (Z_TYPE_P ( args [ 0 ]) != IS_STRING
1017
- || Z_TYPE_P ( args [ 1 ]) != IS_LONG
1018
- || Z_TYPE_P ( args [ 2 ]) != IS_LONG ) {
936
+
937
+ ini_entry = zend_hash_find_ptr ( EG ( ini_directives ), Z_STR_P ( args [ 0 ]));
938
+ if (! ini_entry ) {
939
+ ZVAL_FALSE ( result );
940
+ } else if ( ini_entry -> modifiable != ZEND_INI_SYSTEM ) {
1019
941
return FAILURE ;
942
+ } else if (ini_entry -> value ) {
943
+ ZVAL_STR_COPY (result , ini_entry -> value );
944
+ } else {
945
+ ZVAL_EMPTY_STRING (result );
1020
946
}
1021
- /* pass */
1022
- } else {
1023
- return FAILURE ;
947
+ return SUCCESS ;
1024
948
}
1025
- } else {
1026
- return FAILURE ;
1027
949
}
1028
950
1029
- func = zend_hash_find_ptr (CG (function_table ), name );
1030
- if (!func || func -> type != ZEND_INTERNAL_FUNCTION ) {
951
+ if (!can_ct_eval_func_call (name , num_args , args )) {
1031
952
return FAILURE ;
1032
953
}
1033
954
0 commit comments