Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ PHP NEWS
types. (Weilin Du)
. Fixed MessageFormatter::parse() and parseMessage() returning PHP_INT_MIN
as float rather than int on 64-bit platforms. (Weilin Du)
. Fixed UConverter::transcode() silently truncating from_subst and to_subst
option lengths greater than 127 bytes. (Weilin Du)

- JSON:
. Enriched JSON last error / exception message with error location.
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ PHP 8.6 UPGRADE NOTES
int, rather than float, on 64-bit platforms when parsing integer values.
. The $type parameter of IntlBreakIterator::getPartsIterator() has been
changed from string to int to match the underlying implementation.
. UConverter::transcode() now rejects from_subst and to_subst option values
longer than 127 bytes instead of silently truncating the length before
passing it to ICU.

- PCNTL:
. pcntl_alarm() now raises a ValueError if the seconds argument is
Expand Down
14 changes: 12 additions & 2 deletions ext/intl/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,16 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv,
}
/* }}} */

static void php_converter_set_subst_chars(UConverter *cnv, zend_string *subst, UErrorCode *error)
{
if (ZSTR_LEN(subst) > SCHAR_MAX) {
*error = U_ILLEGAL_ARGUMENT_ERROR;
return;
}

ucnv_setSubstChars(cnv, ZSTR_VAL(subst), (int8_t) ZSTR_LEN(subst), error);
}

/* {{{ */
#define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1);
PHP_METHOD(UConverter, reasonText) {
Expand Down Expand Up @@ -761,13 +771,13 @@ PHP_METHOD(UConverter, transcode) {
(tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL &&
Z_TYPE_P(tmpzval) == IS_STRING) {
error = U_ZERO_ERROR;
ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
php_converter_set_subst_chars(src_cnv, Z_STR_P(tmpzval), &error);
}
if (U_SUCCESS(error) &&
(tmpzval = zend_hash_str_find_deref(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL &&
Z_TYPE_P(tmpzval) == IS_STRING) {
error = U_ZERO_ERROR;
ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
php_converter_set_subst_chars(dest_cnv, Z_STR_P(tmpzval), &error);
}
}

Expand Down
17 changes: 15 additions & 2 deletions ext/intl/rangeformatter/rangeformatter_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ zend_object *IntlNumberRangeFormatter_object_create(zend_class_entry *ce)
return &intern->zo;
}

static icu::Formattable rangeformatter_create_formattable(zval *number)
{
icu::Formattable formattable;

if (Z_TYPE_P(number) == IS_DOUBLE) {
formattable.setDouble(Z_DVAL_P(number));
} else {
formattable.setInt64(static_cast<int64_t>(Z_LVAL_P(number)));
}

return formattable;
}

U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, __construct)
{
ZEND_PARSE_PARAMETERS_NONE();
Expand Down Expand Up @@ -154,8 +167,8 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format)

UErrorCode error = U_ZERO_ERROR;

icu::Formattable start_formattable(Z_TYPE_P(start) == IS_DOUBLE ? Z_DVAL_P(start) : Z_LVAL_P(start));
icu::Formattable end_formattable(Z_TYPE_P(end) == IS_DOUBLE ? Z_DVAL_P(end) : Z_LVAL_P(end));
icu::Formattable start_formattable = rangeformatter_create_formattable(start);
icu::Formattable end_formattable = rangeformatter_create_formattable(end);

UnicodeString result = RANGEFORMATTER_OBJECT(obj)->formatFormattableRange(start_formattable, end_formattable, error).toString(error);

Expand Down
27 changes: 27 additions & 0 deletions ext/intl/tests/rangeformatter/rangeformatter_format_int64.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
IntlNumberRangeFormatter::format() preserves int64 precision
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (!class_exists('IntlNumberRangeFormatter')) {
die('skip IntlNumberRangeFormatter not available');
}
if (PHP_INT_SIZE < 8) {
die('skip 64-bit only');
}
?>
--FILE--
<?php
$formatter = IntlNumberRangeFormatter::createFromSkeleton(
'',
'en_US',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE
);

$formatted = $formatter->format(9007199254740993, 9007199254740993);
var_dump(preg_replace('/[^0-9]/', '', $formatted));
?>
--EXPECT--
string(16) "9007199254740993"
20 changes: 20 additions & 0 deletions ext/intl/tests/uconverter_transcode_subst_length.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
UConverter::transcode() rejects too long substitution strings
--EXTENSIONS--
intl
--INI--
intl.use_exceptions=false
--FILE--
<?php
$subst = str_repeat('A', 129);

var_dump(UConverter::transcode('abc', 'UTF-8', 'ASCII', ['from_subst' => $subst]));
echo intl_get_error_message(), "\n";
var_dump(UConverter::transcode('abc', 'UTF-8', 'ASCII', ['to_subst' => $subst]));
echo intl_get_error_message(), "\n";
?>
--EXPECT--
bool(false)
UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR
bool(false)
UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR
Loading