Commit aea70e03 authored by Neal Norwitz's avatar Neal Norwitz

Fix the refleak in strftime when converting a %Z with a user defined tzinfo.

I inverted some of the conditionals to reduce indent levels.  Hopefully
this makes it a little easier to read.

This code caused the leak:

    class FixedOffset(datetime.tzinfo):
        def tzname(self, dt): return "UTC"

    datetime.time(12, 47, tzinfo=FixedOffset()).strftime('%Z')

This code is very tricky and I'm not positive it works.  However,
it neither crashes nor leaks.
parent cbbe98f0
...@@ -1131,45 +1131,52 @@ format_utcoffset(char *buf, size_t buflen, const char *sep, ...@@ -1131,45 +1131,52 @@ format_utcoffset(char *buf, size_t buflen, const char *sep,
static PyObject * static PyObject *
make_Zreplacement(PyObject *object, PyObject *tzinfoarg) make_Zreplacement(PyObject *object, PyObject *tzinfoarg)
{ {
PyObject *temp;
PyObject *tzinfo = get_tzinfo_member(object); PyObject *tzinfo = get_tzinfo_member(object);
PyObject *Zreplacement = PyString_FromString(""); PyObject *Zreplacement = PyString_FromString("");
if (Zreplacement == NULL) if (Zreplacement == NULL)
return NULL; return NULL;
if (tzinfo != Py_None && tzinfo != NULL) { if (tzinfo == Py_None || tzinfo == NULL)
PyObject *temp; return Zreplacement;
assert(tzinfoarg != NULL); assert(tzinfoarg != NULL);
temp = call_tzname(tzinfo, tzinfoarg); temp = call_tzname(tzinfo, tzinfoarg);
if (temp == NULL) if (temp == NULL)
goto Error; goto Error;
if (temp != Py_None) { if (temp == Py_None) {
Py_DECREF(temp);
return Zreplacement;
}
assert(PyUnicode_Check(temp)); assert(PyUnicode_Check(temp));
/* Since the tzname is getting stuffed into the /* Since the tzname is getting stuffed into the
* format, we have to double any % signs so that * format, we have to double any % signs so that
* strftime doesn't treat them as format codes. * strftime doesn't treat them as format codes.
*/ */
Py_DECREF(Zreplacement); Py_DECREF(Zreplacement);
Zreplacement = PyObject_CallMethod(temp, "replace", Zreplacement = PyObject_CallMethod(temp, "replace", "ss", "%", "%%");
"ss", "%", "%%");
Py_DECREF(temp); Py_DECREF(temp);
if (Zreplacement == NULL) if (Zreplacement == NULL)
return NULL; return NULL;
if (PyUnicode_Check(Zreplacement)) { if (PyUnicode_Check(Zreplacement)) {
Zreplacement = /* XXX(nnorwitz): this is really convoluted, is it correct? */
_PyUnicode_AsDefaultEncodedString( PyObject *Zreplacement2 =
Zreplacement, NULL); _PyUnicode_AsDefaultEncodedString(Zreplacement, NULL);
if (Zreplacement == NULL) if (Zreplacement2 == NULL)
return NULL; return NULL;
Py_INCREF(Zreplacement); Py_INCREF(Zreplacement2);
/* Zreplacement is owned, but Zreplacement2 is borrowed.
If they are different, we have to release Zreplacement. */
if (Zreplacement != Zreplacement2) {
Py_DECREF(Zreplacement);
}
Zreplacement = Zreplacement2;
} }
if (!PyString_Check(Zreplacement)) { if (!PyString_Check(Zreplacement)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"tzname.replace() did not return a string"); "tzname.replace() did not return a string");
goto Error; goto Error;
} }
}
else
Py_DECREF(temp);
}
return Zreplacement; return Zreplacement;
Error: Error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment