Skip to content

Fixed bug #73239 (DateTime shows strange error message with invalid timezone) #8594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 2, 2022

Conversation

derickr
Copy link
Member

@derickr derickr commented May 20, 2022

No description provided.

@derickr derickr requested review from iluuu1994 and cmb69 May 20, 2022 14:01
@derickr derickr self-assigned this May 20, 2022
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Generally good, but I'm not sure whether we should fix that long standing behavior in a revision.

Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cmb69 I don't think any project other than php-src should depend on specific error messages, so breakage here is unlikely. But since this is not critical master would be fine too.

Edit: Some tests need to be fixed of course. @derickr Now you have the chance to try --bless 😉

?>
--EXPECTF--
Warning: ini_set(): Invalid date.timezone value 'dummy' in %sbug73239.php on line %d
DateTime::__construct(): Invalid date.timezone value 'dummy', we selected the timezone 'UTC' for now.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might have mixed things up? The "we selected the timezone 'UTC' for now" should be on the ini_set() error message (where it makes sense) and not the DateTime::__construct() message (where it doesn't, because of the exception).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch, as is, removes both "we selected the timezone 'UTC' for now" messages; only that test expection isn't in line with that. I agree though, that the message raised from PHP_INI_MH(OnUpdate_date_timezone) might better stay as is (well, not really the wording; I'd go with passive voice instead).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I did not mix this up. The ini_set() warning is correct. At that state, PHP never fell back to UTC, it just shown the warning to hint that you messed up.

The warning for DateTime was correct as in the test, the code is wrong. It should very much tell you there that there was an actual fallback to UTC. And I have updated the wording.

I don't want to change the behaviour here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, but throwing an exception with the message "DateTime::__construct(): UTC was used as timezone, because the date.timezone value 'dummy' is invalid" doesn't make sense. If UTC was used, there is no reason to throw an exception. And when an exception is thrown, that UTC is irrelevant. Or do I miss something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, of course. That's why I originally had removed that part of the sentence. I'll fix that back then. Need more 🍵 .

Copy link
Member Author

@derickr derickr May 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't actually that simple. The location where this warning message is thrown, is in guess_timezone:

        if (!timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) {
            php_error_docref(NULL, E_WARNING, "UTC was used as timezone, because the date.timezone value '%s' is invalid", DATEG(default_timezone));
            return "UTC";
        }

Where the warning is correct. This same guess_timezone function is also called in date_initialize (via get_timezone_info()). get_timezone_info() is used plenty of times, where the warning message should be shown.

However, get_timezone_info() is also called as part of the DateTime constructor, where then the exception message is indeed silly, although it should refuse to construct the DateTime object as it currently does. Instead the exception ought to say the same as the warning from ini_set(). However, having a flag on the function to switch between two error messages is perhaps silly too, so I don't have a real good answer here.

@nikic
Copy link
Member

nikic commented May 27, 2022

I think what we should be doing here is to fail the ini update if the timezone is invalid (i.e. keep the previous valid value). This way we cannot hit this error condition in guess_timezone at all and the problem is nicely resolved.

@derickr
Copy link
Member Author

derickr commented May 27, 2022

OK, with this latest commit, the warning now only shows up when setting a wrong timezone through date.timezone.

@derickr derickr force-pushed the bug73239 branch 2 times, most recently from f7cee44 to 438c798 Compare May 27, 2022 13:50
@@ -497,21 +497,19 @@ timelib_tzinfo *php_date_parse_tzfile_wrapper(const char *formal_tzname, const t
/* {{{ static PHP_INI_MH(OnUpdate_date_timezone) */
static PHP_INI_MH(OnUpdate_date_timezone)
{
if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
DATEG(timezone_valid) = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this assignment is needed anymore?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And possibly the entire timezone_valid flag?

Copy link
Member Author

@derickr derickr May 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps not, but I didn't want to risk just removing it in case there is a weird edge case that I didn't think of, and it is used in other places.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell this is the one place that would assign zero to it, others assign 1 or check for 1. We should probably retarget this change to master though, as there's some minor changes in behavior (as seen in tests).

@derickr derickr changed the base branch from PHP-8.0 to master May 29, 2022 16:21
Comment on lines +485 to 494
if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
return FAILURE;
}

return SUCCESS;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
return FAILURE;
}
return SUCCESS;
return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);

Maybe?

@derickr
Copy link
Member Author

derickr commented May 30, 2022

@nikic You OK with this now?

Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, looks good to me.

@@ -478,19 +477,13 @@ timelib_tzinfo *php_date_parse_tzfile_wrapper(const char *formal_tzname, const t
/* {{{ static PHP_INI_MH(OnUpdate_date_timezone) */
static PHP_INI_MH(OnUpdate_date_timezone)
{
if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
if (new_value && ZSTR_VAL(new_value) && !timelib_timezone_id_is_valid(ZSTR_VAL(new_value), DATE_TIMEZONEDB)) {
php_error_docref(NULL, E_WARNING, "Invalid date.timezone value '%s', using 'UTC' instead", ZSTR_VAL(new_value));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, this isn't using UTC but whatever the old value is. Maybe we should print the old value instead?

@derickr derickr merged commit 171ebb1 into php:master Jun 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants