Skip to content

Commit dd30d34

Browse files
author
raymond.hettinger
committed
Bug #1563759: struct.unpack doens't support buffer protocol objects
git-svn-id: http://svn.python.org/projects/python/trunk@54695 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 1dc624f commit dd30d34

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

Lib/test/test_struct.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,11 +614,19 @@ def test_pack_into_fn():
614614
assertRaises(struct.error, pack_into, small_buf, 0, test_string)
615615
assertRaises(struct.error, pack_into, small_buf, 2, test_string)
616616

617+
def test_unpack_with_buffer():
618+
# SF bug 1563759: struct.unpack doens't support buffer protocol objects
619+
data1 = array.array('B', '\x12\x34\x56\x78')
620+
data2 = buffer('......\x12\x34\x56\x78......', 6, 4)
621+
for data in [data1, data2]:
622+
value, = struct.unpack('>I', data)
623+
vereq(value, 0x12345678)
617624

618625
# Test methods to pack and unpack from buffers rather than strings.
619626
test_unpack_from()
620627
test_pack_into()
621628
test_pack_into_fn()
629+
test_unpack_with_buffer()
622630

623631
def test_bool():
624632
for prefix in tuple("<>!=")+('',):

Modules/_struct.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,17 +1534,35 @@ strings.");
15341534
static PyObject *
15351535
s_unpack(PyObject *self, PyObject *inputstr)
15361536
{
1537+
char *start;
1538+
Py_ssize_t len;
1539+
PyObject *args=NULL, *result;
15371540
PyStructObject *soself = (PyStructObject *)self;
15381541
assert(PyStruct_Check(self));
15391542
assert(soself->s_codes != NULL);
1540-
if (inputstr == NULL || !PyString_Check(inputstr) ||
1541-
PyString_GET_SIZE(inputstr) != soself->s_size) {
1542-
PyErr_Format(StructError,
1543-
"unpack requires a string argument of length %zd",
1544-
soself->s_size);
1545-
return NULL;
1543+
if (inputstr == NULL)
1544+
goto fail;
1545+
if (PyString_Check(inputstr) &&
1546+
PyString_GET_SIZE(inputstr) == soself->s_size) {
1547+
return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
15461548
}
1547-
return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
1549+
args = PyTuple_Pack(1, inputstr);
1550+
if (args == NULL)
1551+
return NULL;
1552+
if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len))
1553+
goto fail;
1554+
if (soself->s_size != len)
1555+
goto fail;
1556+
result = s_unpack_internal(soself, start);
1557+
Py_DECREF(args);
1558+
return result;
1559+
1560+
fail:
1561+
Py_XDECREF(args);
1562+
PyErr_Format(StructError,
1563+
"unpack requires a string argument of length %zd",
1564+
soself->s_size);
1565+
return NULL;
15481566
}
15491567

15501568
PyDoc_STRVAR(s_unpack_from__doc__,

0 commit comments

Comments
 (0)