Commit 44fd158e authored by Marius Gedminas's avatar Marius Gedminas Committed by GitHub

Merge pull request #108 from zopefoundation/segfault-on-unicode

Fix segfault on repr(OOBucket([... non-Latin-1 thingies ...]))
parents 7e205796 05df5d09
...@@ -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 = {
......
...@@ -72,5 +72,18 @@ class TestBTreesUnicode(unittest.TestCase): ...@@ -72,5 +72,18 @@ class TestBTreesUnicode(unittest.TestCase):
self.assertTrue(isinstance(k, str)) self.assertTrue(isinstance(k, str))
self.assertEqual(self.tree[k], v) self.assertEqual(self.tree[k], v)
class TestBTreeBucketUnicode(unittest.TestCase):
def testUnicodeRepr(self):
# Regression test for
# https://github.com/zopefoundation/BTrees/issues/106
items = [(1, u'\uaabb')]
from BTrees.OOBTree import OOBucket
bucket = OOBucket(items)
self.assertEqual(repr(bucket),
'BTrees.OOBTree.OOBucket(%s)' % repr(items))
def test_suite(): def test_suite():
return unittest.makeSuite(TestBTreesUnicode) return unittest.defaultTestLoader.loadTestsFromName(__name__)
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
See `issue 98 See `issue 98
<https://github.com/zopefoundation/BTrees/issues/98>`_. <https://github.com/zopefoundation/BTrees/issues/98>`_.
- Fix segmentation fault in ``bucket_repr()``. See
`issue 106 <https://github.com/zopefoundation/BTrees/issue/106>`_.
4.5.1 (2018-08-09) 4.5.1 (2018-08-09)
------------------ ------------------
......
...@@ -7,22 +7,13 @@ envlist = ...@@ -7,22 +7,13 @@ envlist =
[testenv] [testenv]
usedevelop = true usedevelop = true
deps = extras =
.[test] test
commands = commands =
zope-testrunner --test-path=. --auto-color --auto-progress [] zope-testrunner --test-path=. --auto-color --auto-progress []
[testenv:py27-pure]
basepython =
python2.7
setenv = setenv =
PURE_PYTHON = 1 PYTHONFAULTHANDLER=1
pure: PURE_PYTHON=1
[testenv:py35-pure]
basepython =
python3.5
setenv =
PURE_PYTHON = 1
#[testenv:jython] #[testenv:jython]
#commands = #commands =
...@@ -32,7 +23,6 @@ setenv = ...@@ -32,7 +23,6 @@ setenv =
basepython = basepython =
python2.7 python2.7
deps = deps =
{[testenv]deps}
ZODB ZODB
[testenv:coverage] [testenv:coverage]
...@@ -42,7 +32,6 @@ commands = ...@@ -42,7 +32,6 @@ commands =
coverage run -m zope.testrunner --test-path=. --auto-color --auto-progress [] coverage run -m zope.testrunner --test-path=. --auto-color --auto-progress []
coverage report --fail-under=92 coverage report --fail-under=92
deps = deps =
{[testenv]deps}
coverage coverage
[testenv:docs] [testenv:docs]
...@@ -51,5 +40,5 @@ basepython = ...@@ -51,5 +40,5 @@ basepython =
commands = commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
deps = extras =
.[docs] docs
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