Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix refleak and null pointer deref in unusual error path of :mod:`datetime`.
Copy link
Member

Choose a reason for hiding this comment

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

Please remove it, users should not be impacted by this change. The error case is very unlikely.

Copy link
Member

Choose a reason for hiding this comment

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

I suggested adding it since this PR covers several cases increasing the likelyhood of one of them being hit. If you think it is better to remove it, I don't mind.

Copy link
Member

Choose a reason for hiding this comment

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

Usually, we don't document such fix for an unlikely corner case.

PyLong_FromLong() can only fail if the system has no more free memory.

datetime.datetime.astimezone() reads freed memory, but it only occurs if utcoffset() returns the wrong type. It seems like nobody reported the issue (with a reproducer), so it sounds unlikely to crash in practice (reading freed memory just works in the common case).

25 changes: 21 additions & 4 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3822,9 +3822,26 @@ iso_calendar_date_new_impl(PyTypeObject *type, int year, int week,
return NULL;
}

PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year));
PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week));
PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday));
PyObject *year_object = PyLong_FromLong(year);
if (year_object == NULL) {
Py_DECREF(self);
return NULL;
}
PyTuple_SET_ITEM(self, 0, year_object);

PyObject *week_object = PyLong_FromLong(week);
if (week_object == NULL) {
Py_DECREF(self);
return NULL;
}
PyTuple_SET_ITEM(self, 1, week_object);

PyObject *weekday_object = PyLong_FromLong(weekday);
if (weekday_object == NULL) {
Py_DECREF(self);
return NULL;
}
PyTuple_SET_ITEM(self, 2, weekday_object);

return (PyObject *)self;
}
Expand Down Expand Up @@ -6891,9 +6908,9 @@ datetime_datetime_astimezone_impl(PyDateTime_DateTime *self,
goto naive;
}
else if (!PyDelta_Check(offset)) {
Py_DECREF(offset);
PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s,"
" expected timedelta or None", Py_TYPE(offset)->tp_name);
Comment on lines 6911 to 6912
Copy link
Member

Choose a reason for hiding this comment

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

While we are here, you can use %T which is safer and provides more accurate representation:

Suggested change
PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s,"
" expected timedelta or None", Py_TYPE(offset)->tp_name);
PyErr_Format(PyExc_TypeError, "utcoffset() returned %T,"
" expected timedelta or None", offset);

Py_DECREF(offset);
return NULL;
}
/* result = self - offset */
Expand Down
Loading