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 @@ -62,6 +62,8 @@ PHP NEWS
. Fixed bug GH-20426 (Spoofchecker::setRestrictionLevel() error message
suggests missing constants). (DanielEScherzer)
. Added grapheme_strrev (Yuya Hamada)
. Passing a non-stringable object as a time zone to Intl time zone
argument handling now raises TypeError instead of Error. (Weilin Du)

- JSON:
. Enriched JSON last error / exception message with error location.
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ PHP 8.6 UPGRADE NOTES
array arguments types/values and raise a TypeError/ValueError
accordingly.

- Intl:
. Passing a non-stringable object as a time zone to Intl APIs that accept
time zone objects or strings now raises a TypeError instead of an Error.

- PCNTL:
. pcntl_alarm() now raises a ValueError if the seconds argument is
lower than zero or greater than platform's UINT_MAX.
Expand Down
6 changes: 3 additions & 3 deletions ext/intl/calendar/calendar_methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ U_CFUNC PHP_FUNCTION(intlcal_create_instance)
Z_PARAM_STRING_OR_NULL(locale_str, locale_len)
ZEND_PARSE_PARAMETERS_END();

TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr);
TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr, 1);
if (timeZone == nullptr) {
RETURN_NULL();
}
Expand Down Expand Up @@ -316,7 +316,7 @@ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone)
}

TimeZone *timeZone = timezone_process_timezone_argument(
timezone_object, timezone_string, CALENDAR_ERROR_P(co));
timezone_object, timezone_string, CALENDAR_ERROR_P(co), 2);
if (timeZone == nullptr) {
RETURN_FALSE;
}
Expand Down Expand Up @@ -345,7 +345,7 @@ U_CFUNC PHP_METHOD(IntlCalendar, setTimeZone)
}

TimeZone *timeZone = timezone_process_timezone_argument(
timezone_object, timezone_string, CALENDAR_ERROR_P(co));
timezone_object, timezone_string, CALENDAR_ERROR_P(co), 1);
if (timeZone == nullptr) {
RETURN_FALSE;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/calendar/gregoriancalendar_methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool

if (variant <= 2) {
// From timezone and locale (0 to 2 arguments)
TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr);
TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr, 1);
if (tz == nullptr) {
// TODO: Exception should always occur already?
if (!EG(exception)) {
Expand Down
4 changes: 2 additions & 2 deletions ext/intl/dateformat/dateformat_attrcpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ U_CFUNC PHP_FUNCTION(datefmt_set_timezone)
DATE_FORMAT_METHOD_FETCH_OBJECT;

TimeZone *timezone = timezone_process_timezone_argument(
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 2);
if (timezone == nullptr) {
RETURN_FALSE;
}
Expand All @@ -119,7 +119,7 @@ U_CFUNC PHP_METHOD(IntlDateFormatter, setTimeZone)
DATE_FORMAT_METHOD_FETCH_OBJECT;

TimeZone *timezone = timezone_process_timezone_argument(
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 1);
if (timezone == nullptr) {
RETURN_FALSE;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/dateformat/dateformat_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)

if (explicit_tz || calendar_owned ) {
//we have an explicit time zone or a non-object calendar
timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo));
timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo), 4);
if (timezone == nullptr) {
goto error;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/msgformat/msgformat_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo,
}

if (used_tz == NULL) {
used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err);
used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err, 1);
if (used_tz == NULL) {
continue;
}
Expand Down
42 changes: 42 additions & 0 deletions ext/intl/tests/timezone_argument_type_errors.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
Intl timezone argument APIs reject non-stringable objects with TypeError
--EXTENSIONS--
intl
--FILE--
<?php

function dump_exception(callable $cb): void {
try {
$cb();
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
}

$std = new stdClass();
$calendar = IntlCalendar::createInstance();
$formatter = new IntlDateFormatter(null, IntlDateFormatter::NONE, IntlDateFormatter::NONE);

dump_exception(fn() => intlcal_create_instance($std));
dump_exception(fn() => IntlCalendar::createInstance($std));
dump_exception(fn() => intlcal_set_time_zone($calendar, $std));
dump_exception(fn() => $calendar->setTimeZone($std));
dump_exception(fn() => new IntlGregorianCalendar($std));
dump_exception(fn() => datefmt_create(null, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $std));
dump_exception(fn() => IntlDateFormatter::create(null, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $std));
dump_exception(fn() => new IntlDateFormatter(null, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $std));
dump_exception(fn() => datefmt_set_timezone($formatter, $std));
dump_exception(fn() => $formatter->setTimeZone($std));

?>
--EXPECT--
TypeError: intlcal_create_instance(): Argument #1 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlCalendar::createInstance(): Argument #1 ($timezone) Object of class stdClass could not be converted to string
TypeError: intlcal_set_time_zone(): Argument #2 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlCalendar::setTimeZone(): Argument #1 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlGregorianCalendar::__construct(): Argument #1 ($timezoneOrYear) Object of class stdClass could not be converted to string
TypeError: datefmt_create(): Argument #4 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlDateFormatter::create(): Argument #4 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlDateFormatter::__construct(): Argument #4 ($timezone) Object of class stdClass could not be converted to string
TypeError: datefmt_set_timezone(): Argument #2 ($timezone) Object of class stdClass could not be converted to string
TypeError: IntlDateFormatter::setTimeZone(): Argument #1 ($timezone) Object of class stdClass could not be converted to string
7 changes: 4 additions & 3 deletions ext/intl/timezone/timezone_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static void timezone_throw_exception_with_call_location(const char *msg, const c
/* {{{ timezone_process_timezone_argument
* TimeZone argument processor. outside_error may be nullptr (for static functions/constructors) */
U_CFUNC TimeZone *timezone_process_timezone_argument(
zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error)
zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error, uint32_t arg_num)
{
std::unique_ptr<TimeZone> timeZone;
bool free_string = false;
Expand Down Expand Up @@ -160,8 +160,9 @@ U_CFUNC TimeZone *timezone_process_timezone_argument(
free_string = true;
} else {
if (!EG(exception)) {
// TODO Proper type error
zend_throw_error(nullptr, "Object of class %s could not be converted to string", ZSTR_VAL(timezone_object->ce->name));
zend_argument_type_error(arg_num,
"Object of class %s could not be converted to string",
ZSTR_VAL(timezone_object->ce->name));
}
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/timezone/timezone_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static inline TimeZone_object *php_intl_timezone_fetch_object(zend_object *obj)
}

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

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

Expand Down
Loading