Skip to content

Commit a5dd051

Browse files
committed
feedback
1 parent 5f842ce commit a5dd051

11 files changed

Lines changed: 381 additions & 21 deletions

ext/intl/collator/collator_convert.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,20 @@ U_CFUNC zval* collator_convert_object_to_string( zval* obj, zval *rv )
222222
{
223223
/* cast_object failed => bail out. */
224224
zval_ptr_dtor( zstr );
225-
COLLATOR_CONVERT_RETURN_FAILED( obj );
225+
ZVAL_NULL( zstr );
226+
if( !EG(exception) ) {
227+
zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(obj)->name));
228+
}
229+
return nullptr;
226230
}
227231

228232
/* Object wasn't successfully converted => bail out. */
229233
if( zstr == nullptr )
230234
{
231-
COLLATOR_CONVERT_RETURN_FAILED( obj );
235+
if( !EG(exception) ) {
236+
zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(obj)->name));
237+
}
238+
return nullptr;
232239
}
233240

234241
/* Convert the string to UTF-16. */
@@ -348,7 +355,11 @@ U_CFUNC zend_string *collator_zval_to_string(zval *arg)
348355
return zend_string_copy(Z_STR_P(arg));
349356
}
350357

351-
zend_string *utf8_str = zval_get_string(arg);
358+
zend_string *utf8_str = zval_try_get_string(arg);
359+
if (utf8_str == nullptr) {
360+
return nullptr;
361+
}
362+
352363
zend_string *utf16_str = collator_convert_zstr_utf8_to_utf16(utf8_str);
353364
zend_string_release(utf8_str);
354365
return utf16_str;

ext/intl/collator/collator_sort.cpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576;
5050

5151
static const size_t DEF_UTF16_BUF_SIZE = 1024;
5252

53+
static void collator_copy_error(intl_error *dst, const intl_error *src)
54+
{
55+
intl_error_reset(dst);
56+
dst->code = src->code;
57+
if (src->custom_error_message) {
58+
dst->custom_error_message = zend_string_copy(src->custom_error_message);
59+
}
60+
}
61+
62+
static void collator_report_sort_error(Collator_object *co, const intl_error *sort_error)
63+
{
64+
collator_copy_error(COLLATOR_ERROR_P(co), sort_error);
65+
collator_copy_error(&INTL_G(g_error), sort_error);
66+
67+
if (INTL_G(use_exceptions) && INTL_G(g_error).custom_error_message) {
68+
zend_throw_error_exception(IntlException_ce_ptr, INTL_G(g_error).custom_error_message, 0, 0);
69+
}
70+
}
71+
5372
/* {{{ collator_regular_compare_function */
5473
static int collator_regular_compare_function(zval *result, zval *op1, zval *op2)
5574
{
@@ -236,6 +255,11 @@ static int collator_compare_func(Bucket *f, Bucket *s)
236255
zval *first = &f->val;
237256
zval *second = &s->val;
238257

258+
ZEND_ASSERT(INTL_G(current_collator_error) != nullptr);
259+
if( EG(exception) || U_FAILURE( INTL_ERROR_CODE(*INTL_G(current_collator_error)) ) ) {
260+
return 0;
261+
}
262+
239263
if( INTL_G(compare_func)( &result, first, second) == FAILURE )
240264
return 0;
241265

@@ -300,6 +324,8 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
300324
{
301325
UCollator* saved_collator;
302326
intl_error* saved_collator_error;
327+
intl_error sort_error;
328+
collator_compare_func_t saved_compare_func;
303329
zval* array = nullptr;
304330
HashTable* hash = nullptr;
305331
zend_array* sorted = nullptr;
@@ -322,9 +348,6 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
322348
RETURN_THROWS();
323349
}
324350

325-
/* Set 'compare function' according to sort flags. */
326-
INTL_G(compare_func) = collator_get_compare_function( sort_flags );
327-
328351
hash = Z_ARRVAL_P( array );
329352

330353
/* Copy array, so the in-place modifications will not be visible to the callback function */
@@ -337,23 +360,38 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
337360
}
338361
COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" );
339362

363+
intl_error_init( &sort_error );
364+
340365
/* Save specified collator in the request-global (?) variable. */
341366
saved_collator = INTL_G( current_collator );
342367
saved_collator_error = INTL_G( current_collator_error );
368+
saved_compare_func = INTL_G( compare_func );
343369
INTL_G( current_collator ) = co->ucoll;
344-
INTL_G( current_collator_error ) = COLLATOR_ERROR_P( co );
370+
INTL_G( current_collator_error ) = &sort_error;
371+
INTL_G( compare_func ) = collator_get_compare_function( sort_flags );
345372

346373
/* Sort specified array. */
347374
zend_hash_sort( sorted, collator_compare_func, renumber );
348375

349376
/* Restore saved collator. */
350377
INTL_G( current_collator ) = saved_collator;
351378
INTL_G( current_collator_error ) = saved_collator_error;
379+
INTL_G( compare_func ) = saved_compare_func;
352380

353-
if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) {
381+
if( EG(exception) ) {
382+
zend_array_destroy( sorted );
383+
intl_error_reset( &sort_error );
384+
RETURN_THROWS();
385+
}
386+
387+
if( U_FAILURE( INTL_ERROR_CODE(sort_error) ) ) {
354388
zend_array_destroy( sorted );
389+
collator_report_sort_error(co, &sort_error);
390+
intl_error_reset( &sort_error );
391+
RETURN_FALSE;
355392
}
356-
COLLATOR_CHECK_STATUS( co, "Error comparing array values" );
393+
394+
intl_error_reset( &sort_error );
357395

358396
/* Convert strings in the specified array back to UTF-8. */
359397
collator_convert_hash_from_utf16_to_utf8( sorted, COLLATOR_ERROR_CODE_P( co ) );

ext/intl/tests/collator_sort_conversion_error.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ echo $coll->getErrorMessage(), "\n";
2222
--EXPECT--
2323
bool(false)
2424
bool(true)
25-
Collator::sort(): Error comparing array values: U_INVALID_CHAR_FOUND
25+
Collator::sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
2626
bool(true)
27-
Collator::sort(): Error comparing array values: U_INVALID_CHAR_FOUND
27+
Collator::sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Collator::sort() throws IntlException on conversion errors with intl.use_exceptions
3+
--EXTENSIONS--
4+
intl
5+
--INI--
6+
intl.use_exceptions=1
7+
--FILE--
8+
<?php
9+
class BadString {
10+
public function __toString(): string {
11+
return "\xFF";
12+
}
13+
}
14+
15+
$coll = new Collator('en_US');
16+
17+
$array = ['b', new BadString(), 'a'];
18+
try {
19+
$coll->sort($array, Collator::SORT_STRING);
20+
echo 'no exception', PHP_EOL;
21+
} catch (IntlException $e) {
22+
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
23+
}
24+
var_dump($coll->getErrorCode() === U_INVALID_CHAR_FOUND);
25+
var_dump($array[0], $array[1] instanceof BadString, $array[2]);
26+
27+
$array = ['b' => 'b', 'bad' => new BadString(), 'a' => 'a'];
28+
try {
29+
collator_asort($coll, $array, Collator::SORT_STRING);
30+
echo 'no exception', PHP_EOL;
31+
} catch (IntlException $e) {
32+
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
33+
}
34+
var_dump(array_keys($array));
35+
?>
36+
--EXPECT--
37+
IntlException: Collator::sort(): Error converting string from UTF-8 to UTF-16
38+
bool(true)
39+
string(1) "b"
40+
bool(true)
41+
string(1) "a"
42+
IntlException: collator_asort(): Error converting string from UTF-8 to UTF-16
43+
array(3) {
44+
[0]=>
45+
string(1) "b"
46+
[1]=>
47+
string(3) "bad"
48+
[2]=>
49+
string(1) "a"
50+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Collator::sort() conversion error messages describe the failed conversion
3+
--EXTENSIONS--
4+
intl
5+
--FILE--
6+
<?php
7+
class BadString {
8+
public function __toString(): string {
9+
return "\xFF";
10+
}
11+
}
12+
13+
$coll = new Collator('en_US');
14+
15+
$array = ['a', new BadString()];
16+
var_dump($coll->sort($array, Collator::SORT_REGULAR));
17+
echo $coll->getErrorMessage(), PHP_EOL;
18+
19+
$array = ['a', new BadString()];
20+
var_dump($coll->sort($array, Collator::SORT_STRING));
21+
echo $coll->getErrorMessage(), PHP_EOL;
22+
?>
23+
--EXPECT--
24+
bool(false)
25+
Collator::sort(): Error converting object string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
26+
bool(false)
27+
Collator::sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND

ext/intl/tests/collator_sort_conversion_error_procedural.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ string(1) "b"
3636
bool(true)
3737
string(1) "a"
3838
bool(true)
39-
collator_sort(): Error comparing array values: U_INVALID_CHAR_FOUND
39+
collator_sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
4040
bool(true)
41-
collator_sort(): Error comparing array values: U_INVALID_CHAR_FOUND
41+
collator_sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
4242
bool(false)
4343
array(3) {
4444
[0]=>
@@ -49,6 +49,6 @@ array(3) {
4949
string(1) "a"
5050
}
5151
bool(true)
52-
collator_asort(): Error comparing array values: U_INVALID_CHAR_FOUND
52+
collator_asort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
5353
bool(true)
54-
collator_asort(): Error comparing array values: U_INVALID_CHAR_FOUND
54+
collator_asort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Collator::sort() reports conversion errors in SORT_REGULAR comparisons
2+
Collator::sort() SORT_REGULAR conversion error cleanup paths
33
--EXTENSIONS--
44
intl
55
--FILE--
@@ -11,21 +11,52 @@ class BadRegularString {
1111
}
1212

1313
$coll = new Collator('en_US');
14-
$array = [new BadRegularString(), 1];
1514

15+
$array = [new BadRegularString(), 1];
1616
var_dump($coll->sort($array, Collator::SORT_REGULAR));
1717
var_dump($array[0] instanceof BadRegularString);
1818
var_dump($array[1]);
19-
var_dump(intl_get_error_code() === U_INVALID_CHAR_FOUND);
20-
echo intl_get_error_message(), "\n";
2119
var_dump($coll->getErrorCode() === U_INVALID_CHAR_FOUND);
2220
echo $coll->getErrorMessage(), "\n";
21+
22+
$array = ['a', new BadRegularString()];
23+
var_dump($coll->sort($array, Collator::SORT_REGULAR));
24+
var_dump($coll->getErrorCode() === U_INVALID_CHAR_FOUND);
25+
var_dump($array[0], $array[1] instanceof BadRegularString);
26+
27+
$array = ['10', '9'];
28+
var_dump($coll->sort($array, Collator::SORT_REGULAR));
29+
var_dump($coll->getErrorCode() === U_ZERO_ERROR);
30+
var_dump($array);
31+
32+
$array = ['b', '9'];
33+
var_dump($coll->sort($array, Collator::SORT_REGULAR));
34+
var_dump($coll->getErrorCode() === U_ZERO_ERROR);
35+
var_dump($array);
2336
?>
2437
--EXPECT--
2538
bool(false)
2639
bool(true)
2740
int(1)
2841
bool(true)
29-
Collator::sort(): Error comparing array values: U_INVALID_CHAR_FOUND
42+
Collator::sort(): Error converting object string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
43+
bool(false)
44+
bool(true)
45+
string(1) "a"
46+
bool(true)
47+
bool(true)
3048
bool(true)
31-
Collator::sort(): Error comparing array values: U_INVALID_CHAR_FOUND
49+
array(2) {
50+
[0]=>
51+
string(1) "9"
52+
[1]=>
53+
string(2) "10"
54+
}
55+
bool(true)
56+
bool(true)
57+
array(2) {
58+
[0]=>
59+
string(1) "9"
60+
[1]=>
61+
string(1) "b"
62+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Collator::sort() conversion failure must survive a re-entrant Collator call
3+
--EXTENSIONS--
4+
intl
5+
--FILE--
6+
<?php
7+
class Bad {
8+
public function __toString(): string {
9+
return "\xFF";
10+
}
11+
}
12+
13+
class Toucher {
14+
public static Collator $coll;
15+
16+
public function __toString(): string {
17+
if (self::$coll->getErrorCode() !== U_ZERO_ERROR) {
18+
self::$coll->getLocale(Locale::VALID_LOCALE);
19+
}
20+
return 'z';
21+
}
22+
}
23+
24+
$coll = new Collator('en_US');
25+
Toucher::$coll = $coll;
26+
27+
$array = ['a', new Bad(), 'b', new Toucher()];
28+
29+
var_dump($coll->sort($array, Collator::SORT_STRING));
30+
var_dump($coll->getErrorCode() === U_INVALID_CHAR_FOUND);
31+
echo $coll->getErrorMessage(), PHP_EOL;
32+
var_dump($array[0], $array[1] instanceof Bad, $array[2], $array[3] instanceof Toucher);
33+
?>
34+
--EXPECT--
35+
bool(false)
36+
bool(true)
37+
Collator::sort(): Error converting string from UTF-8 to UTF-16: U_INVALID_CHAR_FOUND
38+
string(1) "a"
39+
bool(true)
40+
string(1) "b"
41+
bool(true)

0 commit comments

Comments
 (0)