@@ -923,6 +923,7 @@ static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s) /* {{{ *
923
923
{
924
924
zval args [2 ];
925
925
zval retval ;
926
+ zend_bool call_failed ;
926
927
927
928
ZVAL_COPY (& args [0 ], & f -> val );
928
929
ZVAL_COPY (& args [1 ], & s -> val );
@@ -931,17 +932,41 @@ static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s) /* {{{ *
931
932
BG (user_compare_fci ).params = args ;
932
933
BG (user_compare_fci ).retval = & retval ;
933
934
BG (user_compare_fci ).no_separation = 0 ;
934
- if (zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == SUCCESS && Z_TYPE (retval ) != IS_UNDEF ) {
935
- zend_long ret = zval_get_long (& retval );
936
- zval_ptr_dtor (& retval );
937
- zval_ptr_dtor (& args [1 ]);
938
- zval_ptr_dtor (& args [0 ]);
939
- return ZEND_NORMALIZE_BOOL (ret );
940
- } else {
941
- zval_ptr_dtor (& args [1 ]);
942
- zval_ptr_dtor (& args [0 ]);
935
+ call_failed = zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == FAILURE || Z_TYPE (retval ) == IS_UNDEF ;
936
+ zval_ptr_dtor (& args [1 ]);
937
+ zval_ptr_dtor (& args [0 ]);
938
+ if (UNEXPECTED (call_failed )) {
943
939
return 0 ;
944
940
}
941
+
942
+ if (UNEXPECTED (Z_TYPE (retval ) == IS_FALSE || Z_TYPE (retval ) == IS_TRUE )) {
943
+ if (!ARRAYG (compare_deprecation_thrown )) {
944
+ php_error_docref (NULL , E_DEPRECATED ,
945
+ "Returning bool from comparison function is deprecated, "
946
+ "return one of -1, 0 or 1 instead" );
947
+ ARRAYG (compare_deprecation_thrown ) = 1 ;
948
+ }
949
+
950
+ if (Z_TYPE (retval ) == IS_FALSE ) {
951
+ /* Retry with swapped operands. */
952
+ ZVAL_COPY (& args [0 ], & s -> val );
953
+ ZVAL_COPY (& args [1 ], & f -> val );
954
+ call_failed = zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == FAILURE || Z_TYPE (retval ) == IS_UNDEF ;
955
+ zval_ptr_dtor (& args [1 ]);
956
+ zval_ptr_dtor (& args [0 ]);
957
+ if (call_failed ) {
958
+ return 0 ;
959
+ }
960
+
961
+ zend_long ret = zval_get_long (& retval );
962
+ zval_ptr_dtor (& retval );
963
+ return - ZEND_NORMALIZE_BOOL (ret );
964
+ }
965
+ }
966
+
967
+ zend_long ret = zval_get_long (& retval );
968
+ zval_ptr_dtor (& retval );
969
+ return ZEND_NORMALIZE_BOOL (ret );
945
970
}
946
971
/* }}} */
947
972
@@ -974,6 +999,7 @@ static int php_array_user_compare(Bucket *a, Bucket *b) /* {{{ */
974
999
#define PHP_ARRAY_CMP_FUNC_BACKUP () \
975
1000
old_user_compare_fci = BG(user_compare_fci); \
976
1001
old_user_compare_fci_cache = BG(user_compare_fci_cache); \
1002
+ ARRAYG(compare_deprecation_thrown) = 0; \
977
1003
BG(user_compare_fci_cache) = empty_fcall_info_cache; \
978
1004
979
1005
#define PHP_ARRAY_CMP_FUNC_RESTORE () \
@@ -1033,7 +1059,7 @@ static inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s) /* {
1033
1059
{
1034
1060
zval args [2 ];
1035
1061
zval retval ;
1036
- zend_long result ;
1062
+ zend_bool call_failed ;
1037
1063
1038
1064
if (f -> key == NULL ) {
1039
1065
ZVAL_LONG (& args [0 ], f -> h );
@@ -1050,16 +1076,49 @@ static inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s) /* {
1050
1076
BG (user_compare_fci ).params = args ;
1051
1077
BG (user_compare_fci ).retval = & retval ;
1052
1078
BG (user_compare_fci ).no_separation = 0 ;
1053
- if ( zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == SUCCESS && Z_TYPE (retval ) != IS_UNDEF ) {
1054
- result = zval_get_long ( & retval );
1055
- zval_ptr_dtor (& retval );
1056
- } else {
1057
- result = 0 ;
1079
+ call_failed = zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == FAILURE || Z_TYPE (retval ) == IS_UNDEF ;
1080
+ zval_ptr_dtor ( & args [ 1 ] );
1081
+ zval_ptr_dtor (& args [ 0 ] );
1082
+ if ( UNEXPECTED ( call_failed )) {
1083
+ return 0 ;
1058
1084
}
1059
1085
1060
- zval_ptr_dtor (& args [0 ]);
1061
- zval_ptr_dtor (& args [1 ]);
1086
+ if (UNEXPECTED (Z_TYPE (retval ) == IS_FALSE || Z_TYPE (retval ) == IS_TRUE )) {
1087
+ if (!ARRAYG (compare_deprecation_thrown )) {
1088
+ php_error_docref (NULL , E_DEPRECATED ,
1089
+ "Returning bool from comparison function is deprecated, "
1090
+ "return one of -1, 0 or 1 instead" );
1091
+ ARRAYG (compare_deprecation_thrown ) = 1 ;
1092
+ }
1093
+
1094
+ if (Z_TYPE (retval ) == IS_FALSE ) {
1095
+ /* Retry with swapped operands. */
1096
+ if (s -> key == NULL ) {
1097
+ ZVAL_LONG (& args [0 ], s -> h );
1098
+ } else {
1099
+ ZVAL_STR_COPY (& args [0 ], s -> key );
1100
+ }
1101
+ if (f -> key == NULL ) {
1102
+ ZVAL_LONG (& args [1 ], f -> h );
1103
+ } else {
1104
+ ZVAL_STR_COPY (& args [1 ], f -> key );
1105
+ }
1106
+
1107
+ call_failed = zend_call_function (& BG (user_compare_fci ), & BG (user_compare_fci_cache )) == FAILURE || Z_TYPE (retval ) == IS_UNDEF ;
1108
+ zval_ptr_dtor (& args [1 ]);
1109
+ zval_ptr_dtor (& args [0 ]);
1110
+ if (call_failed ) {
1111
+ return 0 ;
1112
+ }
1113
+
1114
+ zend_long ret = zval_get_long (& retval );
1115
+ zval_ptr_dtor (& retval );
1116
+ return - ZEND_NORMALIZE_BOOL (ret );
1117
+ }
1118
+ }
1062
1119
1120
+ zend_long result = zval_get_long (& retval );
1121
+ zval_ptr_dtor (& retval );
1063
1122
return ZEND_NORMALIZE_BOOL (result );
1064
1123
}
1065
1124
/* }}} */
0 commit comments