@@ -781,253 +781,174 @@ static inline int ct_eval_array_key_exists(zval *result, zval *op1, zval *op2) {
781781 return SUCCESS ;
782782}
783783
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" )) {
860831 zval * entry ;
861832
862833 if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
863- return FAILURE ;
834+ return false ;
864835 }
865836 ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
837+ /* Throws warning for non int/string values. */
866838 if (Z_TYPE_P (entry ) != IS_LONG && Z_TYPE_P (entry ) != IS_STRING ) {
867- return FAILURE ;
839+ return false ;
868840 }
869841 } 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" )) {
872845 zval * entry ;
873846
874847 if (Z_TYPE_P (args [0 ]) != IS_ARRAY ) {
875- return FAILURE ;
848+ return false ;
876849 }
877850
878851 ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
852+ /* May throw warning during conversion to string. */
879853 if (Z_TYPE_P (entry ) > IS_STRING ) {
880- return FAILURE ;
854+ return false ;
881855 }
882856 } 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;
888858 }
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 ;
940870 } else if (zend_string_equals_literal (name , "implode" )) {
941871 zval * entry ;
942872
943873 if ((Z_TYPE_P (args [0 ]) != IS_STRING || Z_TYPE_P (args [1 ]) != IS_ARRAY )
944874 && (Z_TYPE_P (args [0 ]) != IS_ARRAY || Z_TYPE_P (args [1 ]) != IS_STRING )) {
945- return FAILURE ;
875+ return false ;
946876 }
947877
878+ /* May throw warning during conversion to string. */
948879 if (Z_TYPE_P (args [0 ]) == IS_ARRAY ) {
949880 ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [0 ]), entry ) {
950881 if (Z_TYPE_P (entry ) > IS_STRING ) {
951- return FAILURE ;
882+ return false ;
952883 }
953884 } ZEND_HASH_FOREACH_END ();
954885 } else {
955886 ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (args [1 ]), entry ) {
956887 if (Z_TYPE_P (entry ) > IS_STRING ) {
957- return FAILURE ;
888+ return false ;
958889 }
959890 } ZEND_HASH_FOREACH_END ();
960891 }
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;
986893 }
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 ) {
992917 return FAILURE ;
993918 }
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 ;
1006926 }
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 ) {
1012934 return FAILURE ;
1013935 }
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 ) {
1019941 return FAILURE ;
942+ } else if (ini_entry -> value ) {
943+ ZVAL_STR_COPY (result , ini_entry -> value );
944+ } else {
945+ ZVAL_EMPTY_STRING (result );
1020946 }
1021- /* pass */
1022- } else {
1023- return FAILURE ;
947+ return SUCCESS ;
1024948 }
1025- } else {
1026- return FAILURE ;
1027949 }
1028950
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 )) {
1031952 return FAILURE ;
1032953 }
1033954
0 commit comments