Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Lib/test/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,15 @@ def test_endian_table_init_subinterpreters(self):
results = executor.map(exec, [code] * 5)
self.assertListEqual(list(results), [None] * 5)

def test_operations_on_half_initialized_Struct(self):
S = struct.Struct.__new__(struct.Struct)

spam = array.array('b', b' ')
for attr in ['iter_unpack', 'pack', 'pack_into',
'unpack', 'unpack_from']:
meth = getattr(S, attr)
self.assertRaises(RuntimeError, meth, spam)
Comment thread
skirpichev marked this conversation as resolved.
Outdated


class UnpackIteratorTest(unittest.TestCase):
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Raise :exc:`RuntimeError`'s when user attempts to call methods on
half-initialized :class:`~struct.Struct` objects, For example, created by
``Struct.__new__(Struct)``. Patch by Sergey B Kirpichev.
25 changes: 19 additions & 6 deletions Modules/_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -1698,8 +1698,6 @@ prepare_s(PyStructObject *self)
return -1;
}

self->s_size = size;
self->s_len = len;
codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
if (codes == NULL) {
PyErr_NoMemory();
Expand All @@ -1709,6 +1707,8 @@ prepare_s(PyStructObject *self)
if (self->s_codes != NULL)
PyMem_Free(self->s_codes);
self->s_codes = codes;
self->s_size = size;
self->s_len = len;

s = fmt;
size = 0;
Expand Down Expand Up @@ -1794,8 +1794,6 @@ static int
Struct___init___impl(PyStructObject *self, PyObject *format)
/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/
{
int ret = 0;

Comment thread
skirpichev marked this conversation as resolved.
if (PyUnicode_Check(format)) {
format = PyUnicode_AsASCIIString(format);
if (format == NULL)
Expand All @@ -1816,8 +1814,10 @@ Struct___init___impl(PyStructObject *self, PyObject *format)

Py_SETREF(self->s_format, format);

ret = prepare_s(self);
return ret;
if (prepare_s(self)) {
return -1;
}
return 0;
Comment thread
skirpichev marked this conversation as resolved.
Outdated
}

static int
Expand Down Expand Up @@ -1897,6 +1897,14 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom,
return NULL;
}

#define ENSURE_STRUCT_IS_READY(self) \
do { \
if (!(self)->s_codes) { \
PyErr_SetString(PyExc_RuntimeError, \
"Struct object is not initialized"); \
return NULL; \
} \
} while (0);

/*[clinic input]
Struct.unpack
Expand All @@ -1917,6 +1925,7 @@ Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
ENSURE_STRUCT_IS_READY(self);
assert(self->s_codes != NULL);
Comment thread
skirpichev marked this conversation as resolved.
Outdated
if (buffer->len != self->s_size) {
PyErr_Format(state->StructError,
Expand Down Expand Up @@ -1949,6 +1958,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
ENSURE_STRUCT_IS_READY(self);
assert(self->s_codes != NULL);

if (offset < 0) {
Expand Down Expand Up @@ -2101,6 +2111,7 @@ Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer)
{
_structmodulestate *state = get_struct_state_structinst(self);
unpackiterobject *iter;
ENSURE_STRUCT_IS_READY(self);

assert(self->s_codes != NULL);

Expand Down Expand Up @@ -2242,6 +2253,7 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)

/* Validate arguments. */
soself = PyStructObject_CAST(self);
ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
assert(soself->s_codes != NULL);
if (nargs != soself->s_len)
Expand Down Expand Up @@ -2285,6 +2297,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)

/* Validate arguments. +1 is for the first arg as buffer. */
soself = PyStructObject_CAST(self);
ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
assert(soself->s_codes != NULL);
if (nargs != (soself->s_len + 2))
Expand Down
Loading