From 3608f0570e634ac127ed9bce10d305d16a19e984 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 4 Apr 2007 20:32:03 +0000 Subject: [PATCH] Bug #1563759: struct.unpack doens't support buffer protocol objects --- Lib/test/test_struct.py | 6 ++++++ Misc/NEWS | 2 ++ Modules/_struct.c | 20 +++++++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 66fd6672f07..7ecb6ac9a04 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -612,8 +612,14 @@ def test_pack_into_fn(): assertRaises(struct.error, pack_into, small_buf, 0, test_string) assertRaises(struct.error, pack_into, small_buf, 2, test_string) +def test_unpack_with_buffer(): + # SF bug 1563759: struct.unpack doens't support buffer protocol objects + data = array.array('B', '\x12\x34\x56\x78') + value, = struct.unpack('>I', data) + vereq(value, 0x12345678) # Test methods to pack and unpack from buffers rather than strings. test_unpack_from() test_pack_into() test_pack_into_fn() +test_unpack_with_buffer() diff --git a/Misc/NEWS b/Misc/NEWS index afbd326b23a..618d5f1e085 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -134,6 +134,8 @@ Core and builtins Extension Modules ----------------- +- Bug #1563759: struct.unpack doens't support buffer protocol objects + - Bug #1686475: Support stat'ing open files on Windows again. - Bug #1647541: Array module's buffer interface can now handle empty arrays. diff --git a/Modules/_struct.c b/Modules/_struct.c index fb509872a7e..ba276b364ec 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1485,17 +1485,31 @@ strings."); static PyObject * s_unpack(PyObject *self, PyObject *inputstr) { + char *start; + int len; + PyObject * args; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (inputstr == NULL || !PyString_Check(inputstr) || - PyString_GET_SIZE(inputstr) != soself->s_size) { + if (inputstr != NULL && PyString_Check(inputstr) && + PyString_GET_SIZE(inputstr) == soself->s_size) { + return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + } + args = PyTuple_Pack(1, inputstr); + if (args == NULL) + return NULL; + if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) { + Py_DECREF(args); + return NULL; + } + Py_DECREF(args); + if (soself->s_size != len) { PyErr_Format(StructError, "unpack requires a string argument of length %zd", soself->s_size); return NULL; } - return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); + return s_unpack_internal(soself, start); } PyDoc_STRVAR(s_unpack_from__doc__,