Skip to content

Commit bb71580

Browse files
committed
ext/intl: Throw TypeError for non-stringable timezone objects
1 parent 630555f commit bb71580

10 files changed

Lines changed: 26 additions & 12 deletions

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ PHP NEWS
6262
. Fixed bug GH-20426 (Spoofchecker::setRestrictionLevel() error message
6363
suggests missing constants). (DanielEScherzer)
6464
. Added grapheme_strrev (Yuya Hamada)
65+
. Passing a non-stringable object as a time zone to Intl time zone
66+
argument handling now raises TypeError instead of Error. (Weilin Du)
6567

6668
- JSON:
6769
. Enriched JSON last error / exception message with error location.

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ PHP 8.6 UPGRADE NOTES
3434
array arguments types/values and raise a TypeError/ValueError
3535
accordingly.
3636

37+
- Intl:
38+
. Passing a non-stringable object as a time zone to Intl APIs that accept
39+
time zone objects or strings now raises a TypeError instead of an Error.
40+
3741
- PCNTL:
3842
. pcntl_alarm() now raises a ValueError if the seconds argument is
3943
lower than zero or greater than platform's UINT_MAX.

ext/intl/calendar/calendar_methods.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ U_CFUNC PHP_FUNCTION(intlcal_create_instance)
8585
Z_PARAM_STRING_OR_NULL(locale_str, locale_len)
8686
ZEND_PARSE_PARAMETERS_END();
8787

88-
TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr);
88+
TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr, 1);
8989
if (timeZone == nullptr) {
9090
RETURN_NULL();
9191
}
@@ -316,7 +316,7 @@ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone)
316316
}
317317

318318
TimeZone *timeZone = timezone_process_timezone_argument(
319-
timezone_object, timezone_string, CALENDAR_ERROR_P(co));
319+
timezone_object, timezone_string, CALENDAR_ERROR_P(co), 2);
320320
if (timeZone == nullptr) {
321321
RETURN_FALSE;
322322
}
@@ -345,7 +345,7 @@ U_CFUNC PHP_METHOD(IntlCalendar, setTimeZone)
345345
}
346346

347347
TimeZone *timeZone = timezone_process_timezone_argument(
348-
timezone_object, timezone_string, CALENDAR_ERROR_P(co));
348+
timezone_object, timezone_string, CALENDAR_ERROR_P(co), 1);
349349
if (timeZone == nullptr) {
350350
RETURN_FALSE;
351351
}

ext/intl/calendar/gregoriancalendar_methods.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool
143143

144144
if (variant <= 2) {
145145
// From timezone and locale (0 to 2 arguments)
146-
TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr);
146+
TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr, 1);
147147
if (tz == nullptr) {
148148
// TODO: Exception should always occur already?
149149
if (!EG(exception)) {

ext/intl/dateformat/dateformat_attrcpp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ U_CFUNC PHP_FUNCTION(datefmt_set_timezone)
9494
DATE_FORMAT_METHOD_FETCH_OBJECT;
9595

9696
TimeZone *timezone = timezone_process_timezone_argument(
97-
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
97+
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 2);
9898
if (timezone == nullptr) {
9999
RETURN_FALSE;
100100
}
@@ -119,7 +119,7 @@ U_CFUNC PHP_METHOD(IntlDateFormatter, setTimeZone)
119119
DATE_FORMAT_METHOD_FETCH_OBJECT;
120120

121121
TimeZone *timezone = timezone_process_timezone_argument(
122-
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
122+
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 1);
123123
if (timezone == nullptr) {
124124
RETURN_FALSE;
125125
}

ext/intl/dateformat/dateformat_create.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
131131

132132
if (explicit_tz || calendar_owned ) {
133133
//we have an explicit time zone or a non-object calendar
134-
timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
134+
timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 4);
135135
if (timezone == nullptr) {
136136
goto error;
137137
}

ext/intl/msgformat/msgformat_helpers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo,
341341
}
342342

343343
if (used_tz == NULL) {
344-
used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err);
344+
used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err, 1);
345345
if (used_tz == NULL) {
346346
continue;
347347
}

ext/intl/tests/dateformat_setTimeZone_error.phpt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ try {
1616
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1717
}
1818

19+
try {
20+
$df->setTimeZone(new stdClass());
21+
} catch (Throwable $e) {
22+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
23+
}
24+
1925
try {
2026
$df->setTimeZone('non existing timezone');
2127
} catch (Throwable $e) {
@@ -24,4 +30,5 @@ try {
2430
?>
2531
--EXPECT--
2632
TypeError: IntlDateFormatter::setTimeZone(): Argument #1 ($timezone) must be of type object|string|null, array given
33+
TypeError: IntlDateFormatter::setTimeZone(): Argument #1 ($timezone) Object of class stdClass could not be converted to string
2734
IntlException: IntlDateFormatter::setTimeZone(): No such time zone: "non existing timezone"

ext/intl/timezone/timezone_class.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ static void timezone_throw_exception_with_call_location(const char *msg, const c
121121
/* {{{ timezone_process_timezone_argument
122122
* TimeZone argument processor. outside_error may be nullptr (for static functions/constructors) */
123123
U_CFUNC TimeZone *timezone_process_timezone_argument(
124-
zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error)
124+
zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error, uint32_t arg_num)
125125
{
126126
std::unique_ptr<TimeZone> timeZone;
127127
bool free_string = false;
@@ -160,8 +160,9 @@ U_CFUNC TimeZone *timezone_process_timezone_argument(
160160
free_string = true;
161161
} else {
162162
if (!EG(exception)) {
163-
// TODO Proper type error
164-
zend_throw_error(nullptr, "Object of class %s could not be converted to string", ZSTR_VAL(timezone_object->ce->name));
163+
zend_argument_type_error(arg_num,
164+
"Object of class %s could not be converted to string",
165+
ZSTR_VAL(timezone_object->ce->name));
165166
}
166167
return nullptr;
167168
}

ext/intl/timezone/timezone_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static inline TimeZone_object *php_intl_timezone_fetch_object(zend_object *obj)
6767
}
6868

6969
zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, zval *ret);
70-
TimeZone *timezone_process_timezone_argument(zend_object *timezone_object, zend_string *timezone_string, intl_error *error);
70+
TimeZone *timezone_process_timezone_argument(zend_object *timezone_object, zend_string *timezone_string, intl_error *error, uint32_t arg_num);
7171

7272
void timezone_object_construct(const TimeZone *zone, zval *object, int owned);
7373

0 commit comments

Comments
 (0)