FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-78724: raise RuntimeError's when calling methods on non-ready Struct()'s by skirpichev · Pull Request #143643 · python/cpython · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (1) .py  (1) .rst  (1) All 3 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
12 changes: 12 additions & 0 deletions Lib/test/test_struct.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,18 @@ 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' ')
self.assertRaises(RuntimeError, S.iter_unpack, spam)
self.assertRaises(RuntimeError, S.pack, 1)
self.assertRaises(RuntimeError, S.pack_into, spam, 1)
self.assertRaises(RuntimeError, S.unpack, spam)
self.assertRaises(RuntimeError, S.unpack_from, spam)
self.assertRaises(RuntimeError, getattr, S, 'format')
self.assertEqual(S.size, -1)


class UnpackIteratorTest(unittest.TestCase):
"""
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.
24 changes: 16 additions & 8 deletions Modules/_struct.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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 @@ -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,7 +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);
assert(self->s_codes != NULL);
ENSURE_STRUCT_IS_READY(self);
if (buffer->len != self->s_size) {
PyErr_Format(state->StructError,
"unpack requires a buffer of %zd bytes",
Expand Down Expand Up @@ -1949,7 +1957,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);
assert(self->s_codes != NULL);
ENSURE_STRUCT_IS_READY(self);

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

assert(self->s_codes != NULL);
ENSURE_STRUCT_IS_READY(self);

if (self->s_size == 0) {
PyErr_Format(state->StructError,
Expand Down Expand Up @@ -2242,8 +2249,8 @@ 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)
{
PyErr_Format(state->StructError,
Expand Down Expand Up @@ -2285,8 +2292,8 @@ 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))
{
if (nargs == 0) {
Expand Down Expand Up @@ -2373,6 +2380,7 @@ static PyObject *
s_get_format(PyObject *op, void *Py_UNUSED(closure))
{
PyStructObject *self = PyStructObject_CAST(op);
ENSURE_STRUCT_IS_READY(self);
return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format),
PyBytes_GET_SIZE(self->s_format));
}
Expand Down
Loading

Back | FazBrowse Home | New Git URL