Skip to content

Commit 30b6b69

Browse files
committed
ext/intl: Fix UConverter::transcode() substitution length truncation
1 parent 69e023f commit 30b6b69

4 files changed

Lines changed: 37 additions & 2 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ PHP NEWS
7373
types. (Weilin Du)
7474
. Fixed MessageFormatter::parse() and parseMessage() returning PHP_INT_MIN
7575
as float rather than int on 64-bit platforms. (Weilin Du)
76+
. Fixed UConverter::transcode() silently truncating from_subst and to_subst
77+
option lengths greater than 127 bytes. (Weilin Du)
7678

7779
- JSON:
7880
. Enriched JSON last error / exception message with error location.

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ PHP 8.6 UPGRADE NOTES
4444
int, rather than float, on 64-bit platforms when parsing integer values.
4545
. The $type parameter of IntlBreakIterator::getPartsIterator() has been
4646
changed from string to int to match the underlying implementation.
47+
. UConverter::transcode() now rejects from_subst and to_subst option values
48+
longer than 127 bytes instead of silently truncating the length before
49+
passing it to ICU.
4750

4851
- PCNTL:
4952
. pcntl_alarm() now raises a ValueError if the seconds argument is

ext/intl/converter/converter.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,16 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv,
682682
}
683683
/* }}} */
684684

685+
static void php_converter_set_subst_chars(UConverter *cnv, zend_string *subst, UErrorCode *error)
686+
{
687+
if (ZSTR_LEN(subst) > SCHAR_MAX) {
688+
*error = U_ILLEGAL_ARGUMENT_ERROR;
689+
return;
690+
}
691+
692+
ucnv_setSubstChars(cnv, ZSTR_VAL(subst), (int8_t) ZSTR_LEN(subst), error);
693+
}
694+
685695
/* {{{ */
686696
#define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1);
687697
PHP_METHOD(UConverter, reasonText) {
@@ -761,13 +771,13 @@ PHP_METHOD(UConverter, transcode) {
761771
(tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL &&
762772
Z_TYPE_P(tmpzval) == IS_STRING) {
763773
error = U_ZERO_ERROR;
764-
ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
774+
php_converter_set_subst_chars(src_cnv, Z_STR_P(tmpzval), &error);
765775
}
766776
if (U_SUCCESS(error) &&
767777
(tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL &&
768778
Z_TYPE_P(tmpzval) == IS_STRING) {
769779
error = U_ZERO_ERROR;
770-
ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
780+
php_converter_set_subst_chars(dest_cnv, Z_STR_P(tmpzval), &error);
771781
}
772782
}
773783

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
UConverter::transcode() rejects too long substitution strings
3+
--EXTENSIONS--
4+
intl
5+
--INI--
6+
intl.use_exceptions=false
7+
--FILE--
8+
<?php
9+
$subst = str_repeat('A', 129);
10+
11+
var_dump(UConverter::transcode('abc', 'UTF-8', 'ASCII', ['from_subst' => $subst]));
12+
var_dump(intl_get_error_code());
13+
var_dump(UConverter::transcode('abc', 'UTF-8', 'ASCII', ['to_subst' => $subst]));
14+
var_dump(intl_get_error_code());
15+
?>
16+
--EXPECT--
17+
bool(false)
18+
int(1)
19+
bool(false)
20+
int(1)

0 commit comments

Comments
 (0)