Commit e2243331 authored by Marius Gedminas's avatar Marius Gedminas

Fix segfault in bucket_repr() on Python 3

Fixes #106.

The bug was in not checking the return value of
PyUnicode_AsLatin1String() and passing a NULL to PyOS_snprintf().

The fix is to use PyUnicode_FromFormat() and avoid all the hassle of
manual encoding/sprintf/decoding and even calling repr().
parent 189d7728
...@@ -1814,51 +1814,40 @@ static PyObject * ...@@ -1814,51 +1814,40 @@ static PyObject *
bucket_repr(Bucket *self) bucket_repr(Bucket *self)
{ {
PyObject *i, *r; PyObject *i, *r;
#ifdef PY3K #ifndef PY3K
PyObject *rb;
#endif
char repr[10000]; char repr[10000];
int rv; int rv;
#endif
i = bucket_items(self, NULL, NULL); i = bucket_items(self, NULL, NULL);
if (!i) if (!i)
{ {
return NULL; return NULL;
} }
#ifdef PY3K
r = PyUnicode_FromFormat("%s(%R)", Py_TYPE(self)->tp_name, i);
Py_DECREF(i);
return r;
#else
r = PyObject_Repr(i); r = PyObject_Repr(i);
Py_DECREF(i); Py_DECREF(i);
if (!r) if (!r)
{ {
return NULL; return NULL;
} }
#ifdef PY3K
rb = PyUnicode_AsLatin1String(r);
rv = PyOS_snprintf(repr, sizeof(repr),
"%s(%s)", Py_TYPE(self)->tp_name,
PyBytes_AsString(rb));
Py_DECREF(rb);
#else
rv = PyOS_snprintf(repr, sizeof(repr), rv = PyOS_snprintf(repr, sizeof(repr),
"%s(%s)", Py_TYPE(self)->tp_name, "%s(%s)", Py_TYPE(self)->tp_name,
PyBytes_AS_STRING(r)); PyBytes_AS_STRING(r));
#endif
if (rv > 0 && (size_t)rv < sizeof(repr)) if (rv > 0 && (size_t)rv < sizeof(repr))
{ {
Py_DECREF(r); Py_DECREF(r);
#ifdef PY3K
return PyUnicode_DecodeLatin1(repr, strlen(repr), "surrogateescape");
#else
return PyBytes_FromStringAndSize(repr, strlen(repr)); return PyBytes_FromStringAndSize(repr, strlen(repr));
#endif
} }
else else
{ {
/* The static buffer wasn't big enough */ /* The static buffer wasn't big enough */
int size; int size;
PyObject *s; PyObject *s;
#ifdef PY3K
PyObject *result;
#endif
/* 3 for the parens and the null byte */ /* 3 for the parens and the null byte */
size = strlen(Py_TYPE(self)->tp_name) + PyBytes_GET_SIZE(r) + 3; size = strlen(Py_TYPE(self)->tp_name) + PyBytes_GET_SIZE(r) + 3;
s = PyBytes_FromStringAndSize(NULL, size); s = PyBytes_FromStringAndSize(NULL, size);
...@@ -1869,14 +1858,9 @@ bucket_repr(Bucket *self) ...@@ -1869,14 +1858,9 @@ bucket_repr(Bucket *self)
PyOS_snprintf(PyBytes_AS_STRING(s), size, PyOS_snprintf(PyBytes_AS_STRING(s), size,
"%s(%s)", Py_TYPE(self)->tp_name, PyBytes_AS_STRING(r)); "%s(%s)", Py_TYPE(self)->tp_name, PyBytes_AS_STRING(r));
Py_DECREF(r); Py_DECREF(r);
#ifdef PY3K
result = PyUnicode_FromEncodedObject(s, "latin1", "surrogateescape");
Py_DECREF(s);
return result;
#else
return s; return s;
#endif
} }
#endif
} }
static PyTypeObject BucketType = { static PyTypeObject BucketType = {
......
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