Skip to content

Commit 69a5eec

Browse files
committed
address review: redo patch to use s_codes
1 parent f542173 commit 69a5eec

File tree

3 files changed

+19
-32
lines changed

3 files changed

+19
-32
lines changed

Lib/test/test_struct.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ def test_Struct_reinitialization(self):
579579

580580
def check_sizeof(self, format_str, number_of_codes):
581581
# The size of 'PyStructObject'
582-
totalsize = support.calcobjsize('2n3PB')
582+
totalsize = support.calcobjsize('2n3P')
583583
# The size taken up by the 'formatcode' dynamic array
584584
totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
585585
support.check_sizeof(self, struct.Struct(format_str), totalsize)
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
Prevent crashes due to using half-initialized :class:`~struct.Struct`
2-
objects. For example, created by ``Struct.__new__(Struct)``. Calling the
3-
``Struct.__new__()`` dunder without required argument now is deprecated.
4-
Calling :meth:`~object.__init__` dunder method of :class:`~struct.Struct`
5-
object on initialized object now also is deprecated. Patch by Sergey B
6-
Kirpichev.
1+
Raise :exc:`RuntimeError`'s when user attempts to call methods on
2+
half-initialized :class:`~struct.Struct` objects, For example, created by
3+
``Struct.__new__(Struct)``. Patch by Sergey B Kirpichev.

Modules/_struct.c

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ typedef struct {
7070
formatcode *s_codes;
7171
PyObject *s_format;
7272
PyObject *weakreflist; /* List of weak references */
73-
bool ready;
7473
} PyStructObject;
7574

7675
#define PyStructObject_CAST(op) ((PyStructObject *)(op))
@@ -1699,8 +1698,6 @@ prepare_s(PyStructObject *self)
16991698
return -1;
17001699
}
17011700

1702-
self->s_size = size;
1703-
self->s_len = len;
17041701
codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
17051702
if (codes == NULL) {
17061703
PyErr_NoMemory();
@@ -1710,6 +1707,8 @@ prepare_s(PyStructObject *self)
17101707
if (self->s_codes != NULL)
17111708
PyMem_Free(self->s_codes);
17121709
self->s_codes = codes;
1710+
self->s_size = size;
1711+
self->s_len = len;
17131712

17141713
s = fmt;
17151714
size = 0;
@@ -1774,7 +1773,6 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17741773
s->s_codes = NULL;
17751774
s->s_size = -1;
17761775
s->s_len = -1;
1777-
s->ready = false;
17781776
}
17791777
return self;
17801778
}
@@ -1819,7 +1817,6 @@ Struct___init___impl(PyStructObject *self, PyObject *format)
18191817
if (prepare_s(self)) {
18201818
return -1;
18211819
}
1822-
self->ready = true;
18231820
return 0;
18241821
}
18251822

@@ -1900,6 +1897,14 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom,
19001897
return NULL;
19011898
}
19021899

1900+
#define ENSURE_STRUCT_IS_READY(self) \
1901+
do { \
1902+
if (!(self)->s_codes) { \
1903+
PyErr_SetString(PyExc_RuntimeError, \
1904+
"Struct object is not initialized"); \
1905+
return NULL; \
1906+
} \
1907+
} while (0);
19031908

19041909
/*[clinic input]
19051910
Struct.unpack
@@ -1920,10 +1925,7 @@ Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
19201925
/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
19211926
{
19221927
_structmodulestate *state = get_struct_state_structinst(self);
1923-
if (!self->ready) {
1924-
PyErr_SetString(PyExc_RuntimeError, "Call unpack on non-initialized Struct()");
1925-
return NULL;
1926-
}
1928+
ENSURE_STRUCT_IS_READY(self);
19271929
assert(self->s_codes != NULL);
19281930
if (buffer->len != self->s_size) {
19291931
PyErr_Format(state->StructError,
@@ -1956,10 +1958,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
19561958
/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
19571959
{
19581960
_structmodulestate *state = get_struct_state_structinst(self);
1959-
if (!self->ready) {
1960-
PyErr_SetString(PyExc_RuntimeError, "Call unpack_from on non-initialized Struct()");
1961-
return NULL;
1962-
}
1961+
ENSURE_STRUCT_IS_READY(self);
19631962
assert(self->s_codes != NULL);
19641963

19651964
if (offset < 0) {
@@ -2112,10 +2111,7 @@ Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer)
21122111
{
21132112
_structmodulestate *state = get_struct_state_structinst(self);
21142113
unpackiterobject *iter;
2115-
if (!self->ready) {
2116-
PyErr_SetString(PyExc_RuntimeError, "Call iter_unpack on non-initialized Struct()");
2117-
return NULL;
2118-
}
2114+
ENSURE_STRUCT_IS_READY(self);
21192115

21202116
assert(self->s_codes != NULL);
21212117

@@ -2257,10 +2253,7 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
22572253

22582254
/* Validate arguments. */
22592255
soself = PyStructObject_CAST(self);
2260-
if (!soself->ready) {
2261-
PyErr_SetString(PyExc_RuntimeError, "Call pack on non-initialized Struct()");
2262-
return NULL;
2263-
}
2256+
ENSURE_STRUCT_IS_READY(soself);
22642257
assert(PyStruct_Check(self, state));
22652258
assert(soself->s_codes != NULL);
22662259
if (nargs != soself->s_len)
@@ -2304,10 +2297,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
23042297

23052298
/* Validate arguments. +1 is for the first arg as buffer. */
23062299
soself = PyStructObject_CAST(self);
2307-
if (!soself->ready) {
2308-
PyErr_SetString(PyExc_RuntimeError, "Call pack_into on non-initialized Struct()");
2309-
return NULL;
2310-
}
2300+
ENSURE_STRUCT_IS_READY(soself);
23112301
assert(PyStruct_Check(self, state));
23122302
assert(soself->s_codes != NULL);
23132303
if (nargs != (soself->s_len + 2))

0 commit comments

Comments
 (0)