-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
gh-125318: Prevent segfaults when zoneinfo is used with "false friends" #139132
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
base: main
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Fixes a segmentation fault that would happen if :class:`zoneinfo.ZoneInfo` | ||
| were used with certain non-:class:`datetime.datetime` classes. Patch by Paul | ||
| Ganssle |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -2197,7 +2197,22 @@ find_ttinfo(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *dt) | |||||||
| return NULL; | ||||||||
| } | ||||||||
|
|
||||||||
| unsigned char fold = PyDateTime_DATE_GET_FOLD(dt); | ||||||||
| unsigned char fold; | ||||||||
| if (PyDateTime_Check(dt)) { | ||||||||
| fold = PyDateTime_DATE_GET_FOLD(dt); | ||||||||
| } else { | ||||||||
| PyObject *fold_obj = PyObject_GetAttrString(dt, "fold"); | ||||||||
| if (fold_obj == NULL) { | ||||||||
| return NULL; | ||||||||
| } | ||||||||
|
|
||||||||
| fold = (unsigned char)PyLong_AsLong(fold_obj); | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Strictly speaking, this is an undefined behavior. You can use But long fold_long = PyLong_AsLong(fold_obj);
Py_DECREF(fold_obj);
if (...) {...}
fold = `(unsigned char)fold_long; |
||||||||
| Py_DECREF(fold_obj); | ||||||||
| if (PyErr_Occurred()) { | ||||||||
| return NULL; | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| assert(fold < 2); | ||||||||
| int64_t *local_transitions = self->trans_list_wall[fold]; | ||||||||
| size_t num_trans = self->num_transitions; | ||||||||
|
|
@@ -2206,10 +2221,23 @@ find_ttinfo(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *dt) | |||||||
| return self->ttinfo_before; | ||||||||
| } | ||||||||
| else if (!num_trans || ts > local_transitions[self->num_transitions - 1]) { | ||||||||
| return find_tzrule_ttinfo(&(self->tzrule_after), ts, fold, | ||||||||
| PyDateTime_GET_YEAR(dt)); | ||||||||
| } | ||||||||
| else { | ||||||||
| int year; | ||||||||
| if (PyDateTime_Check(dt)) { | ||||||||
| year = PyDateTime_GET_YEAR(dt); | ||||||||
| } else { | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick.
Suggested change
|
||||||||
| PyObject *year_obj = PyObject_GetAttrString(dt, "year"); | ||||||||
| if (year_obj == NULL) { | ||||||||
| return NULL; | ||||||||
| } | ||||||||
|
|
||||||||
| year = PyLong_AsLong(year_obj); | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Possible integer overflow here. Use And do we need an additional range check before passing it to |
||||||||
| Py_DECREF(year_obj); | ||||||||
| if (PyErr_Occurred()) { | ||||||||
| return NULL; | ||||||||
| } | ||||||||
| } | ||||||||
| return find_tzrule_ttinfo(&(self->tzrule_after), ts, fold, year); | ||||||||
| } else { | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| size_t idx = _bisect(ts, local_transitions, self->num_transitions) - 1; | ||||||||
| assert(idx < self->num_transitions); | ||||||||
| return self->trans_ttinfos[idx]; | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.