@@ -50,6 +50,17 @@ static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576;
5050
5151static const size_t DEF_UTF16_BUF_SIZE = 1024 ;
5252
53+ static void collator_report_sort_error (Collator_object *co, const intl_error *sort_error)
54+ {
55+ if (sort_error->custom_error_message ) {
56+ intl_errors_set (
57+ COLLATOR_ERROR_P (co), sort_error->code ,
58+ ZSTR_VAL (sort_error->custom_error_message ));
59+ } else {
60+ intl_errors_set_code (COLLATOR_ERROR_P (co), sort_error->code );
61+ }
62+ }
63+
5364/* {{{ collator_regular_compare_function */
5465static int collator_regular_compare_function (zval *result, zval *op1, zval *op2)
5566{
@@ -59,12 +70,20 @@ static int collator_regular_compare_function(zval *result, zval *op1, zval *op2)
5970 zval norm1, norm2;
6071 zval *num1_p = nullptr , *num2_p = nullptr ;
6172 zval *norm1_p = nullptr , *norm2_p = nullptr ;
62- zval *str1_p, *str2_p;
73+ zval *str1_p = nullptr , *str2_p = nullptr ;
6374
6475 ZVAL_NULL (&str1);
6576 str1_p = collator_convert_object_to_string ( op1, &str1 );
77+ if ( str1_p == nullptr ) {
78+ return FAILURE ;
79+ }
80+
6681 ZVAL_NULL (&str2);
6782 str2_p = collator_convert_object_to_string ( op2, &str2 );
83+ if ( str2_p == nullptr ) {
84+ rc = FAILURE ;
85+ goto cleanup;
86+ }
6887
6988 /* If both args are strings AND either of args is not numeric string
7089 * then use ICU-compare. Otherwise PHP-compare. */
@@ -90,9 +109,17 @@ static int collator_regular_compare_function(zval *result, zval *op1, zval *op2)
90109 * just convert it to utf8.
91110 */
92111 norm1_p = collator_convert_zstr_utf16_to_utf8 ( str1_p, &norm1 );
112+ if ( norm1_p == nullptr ) {
113+ rc = FAILURE ;
114+ goto cleanup;
115+ }
93116
94117 /* num2 is not set but str2 is string => do normalization. */
95118 norm2_p = collator_normalize_sort_argument ( str2_p, &norm2 );
119+ if ( norm2_p == nullptr ) {
120+ rc = FAILURE ;
121+ goto cleanup;
122+ }
96123 }
97124 else
98125 {
@@ -109,25 +136,40 @@ static int collator_regular_compare_function(zval *result, zval *op1, zval *op2)
109136 {
110137 /* num1 is not set if str1 or str2 is not a string => do normalization. */
111138 norm1_p = collator_normalize_sort_argument ( str1_p, &norm1 );
139+ if ( norm1_p == nullptr ) {
140+ rc = FAILURE ;
141+ goto cleanup;
142+ }
112143
113144 /* if num1 is not set then num2 is not set as well => do normalization. */
114145 norm2_p = collator_normalize_sort_argument ( str2_p, &norm2 );
146+ if ( norm2_p == nullptr ) {
147+ rc = FAILURE ;
148+ goto cleanup;
149+ }
115150 }
116151
117152 rc = compare_function ( result, norm1_p, norm2_p );
153+ }
118154
155+ cleanup:
156+ if ( norm1_p )
119157 zval_ptr_dtor ( norm1_p );
158+
159+ if ( norm2_p )
120160 zval_ptr_dtor ( norm2_p );
121- }
122161
123162 if ( num1_p )
124163 zval_ptr_dtor ( num1_p );
125164
126165 if ( num2_p )
127166 zval_ptr_dtor ( num2_p );
128167
129- zval_ptr_dtor ( str1_p );
130- zval_ptr_dtor ( str2_p );
168+ if ( str1_p )
169+ zval_ptr_dtor ( str1_p );
170+
171+ if ( str2_p )
172+ zval_ptr_dtor ( str2_p );
131173
132174 return rc;
133175}
@@ -170,9 +212,16 @@ static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2)
170212*/
171213static int collator_icu_compare_function (zval *result, zval *op1, zval *op2)
172214{
173- int rc = SUCCESS ;
174215 zend_string *str1 = collator_zval_to_string (op1);
216+ if ( str1 == nullptr ) {
217+ return FAILURE ;
218+ }
219+
175220 zend_string *str2 = collator_zval_to_string (op2);
221+ if ( str2 == nullptr ) {
222+ zend_string_release (str1);
223+ return FAILURE ;
224+ }
176225
177226 /* Compare the strings using ICU. */
178227 ZEND_ASSERT (INTL_G (current_collator) != nullptr );
@@ -184,7 +233,7 @@ static int collator_icu_compare_function(zval *result, zval *op1, zval *op2)
184233 zend_string_release (str1);
185234 zend_string_release (str2);
186235
187- return rc ;
236+ return SUCCESS ;
188237}
189238/* }}} */
190239
@@ -197,6 +246,11 @@ static int collator_compare_func(Bucket *f, Bucket *s)
197246 zval *first = &f->val ;
198247 zval *second = &s->val ;
199248
249+ ZEND_ASSERT (INTL_G (current_collator_error) != nullptr );
250+ if ( EG (exception) || U_FAILURE ( INTL_ERROR_CODE (*INTL_G (current_collator_error)) ) ) {
251+ return 0 ;
252+ }
253+
200254 if ( INTL_G (compare_func)( &result, first, second) == FAILURE )
201255 return 0 ;
202256
@@ -260,6 +314,9 @@ static collator_compare_func_t collator_get_compare_function( const zend_long so
260314static void collator_sort_internal ( int renumber, INTERNAL_FUNCTION_PARAMETERS )
261315{
262316 UCollator* saved_collator;
317+ intl_error* saved_collator_error;
318+ intl_error sort_error;
319+ collator_compare_func_t saved_compare_func;
263320 zval* array = nullptr ;
264321 HashTable* hash = nullptr ;
265322 zend_array* sorted = nullptr ;
@@ -282,9 +339,6 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
282339 RETURN_THROWS ();
283340 }
284341
285- /* Set 'compare function' according to sort flags. */
286- INTL_G (compare_func) = collator_get_compare_function ( sort_flags );
287-
288342 hash = Z_ARRVAL_P ( array );
289343
290344 /* Copy array, so the in-place modifications will not be visible to the callback function */
@@ -297,15 +351,38 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
297351 }
298352 COLLATOR_CHECK_STATUS ( co, " Error converting hash from UTF-8 to UTF-16" );
299353
354+ intl_error_init ( &sort_error );
355+
300356 /* Save specified collator in the request-global (?) variable. */
301357 saved_collator = INTL_G ( current_collator );
358+ saved_collator_error = INTL_G ( current_collator_error );
359+ saved_compare_func = INTL_G ( compare_func );
302360 INTL_G ( current_collator ) = co->ucoll ;
361+ INTL_G ( current_collator_error ) = &sort_error;
362+ INTL_G ( compare_func ) = collator_get_compare_function ( sort_flags );
303363
304364 /* Sort specified array. */
305365 zend_hash_sort ( sorted, collator_compare_func, renumber );
306366
307367 /* Restore saved collator. */
308368 INTL_G ( current_collator ) = saved_collator;
369+ INTL_G ( current_collator_error ) = saved_collator_error;
370+ INTL_G ( compare_func ) = saved_compare_func;
371+
372+ if ( EG (exception) ) {
373+ zend_array_destroy ( sorted );
374+ intl_error_reset ( &sort_error );
375+ RETURN_THROWS ();
376+ }
377+
378+ if ( U_FAILURE ( INTL_ERROR_CODE (sort_error) ) ) {
379+ zend_array_destroy ( sorted );
380+ collator_report_sort_error (co, &sort_error);
381+ intl_error_reset ( &sort_error );
382+ RETURN_FALSE ;
383+ }
384+
385+ intl_error_reset ( &sort_error );
309386
310387 /* Convert strings in the specified array back to UTF-8. */
311388 collator_convert_hash_from_utf16_to_utf8 ( sorted, COLLATOR_ERROR_CODE_P ( co ) );
0 commit comments