]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-78724: Initialize struct.Struct in __new__ (GH-94532)
authorKumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Sun, 25 Sep 2022 13:32:48 +0000 (19:02 +0530)
committerGitHub <noreply@github.com>
Sun, 25 Sep 2022 13:32:48 +0000 (14:32 +0100)
Closes https://github.com/python/cpython/issues/75960
Closes https://github.com/python/cpython/issues/78724

Lib/test/test_struct.py
Misc/NEWS.d/next/Library/2022-07-03-16-26-35.gh-issue-78724.XNiJzf.rst [new file with mode: 0644]
Modules/_struct.c
Modules/clinic/_struct.c.h

index ab738770546c0b8168b67bff00b37c698fba51d4..b0f11af1a7892e6969ee9aea7252f4210c001b0c 100644 (file)
@@ -700,6 +700,20 @@ class StructTest(unittest.TestCase):
                 with self.assertRaises(TypeError):
                     cls.x = 1
 
+    @support.cpython_only
+    def test__struct_Struct__new__initialized(self):
+        # See https://github.com/python/cpython/issues/78724
+
+        s = struct.Struct.__new__(struct.Struct, "b")
+        s.unpack_from(b"abcd")
+
+    @support.cpython_only
+    def test__struct_Struct_subclassing(self):
+        class Bob(struct.Struct):
+            pass
+
+        s = Bob("b")
+        s.unpack_from(b"abcd")
 
     def test_issue35714(self):
         # Embedded null characters should not be allowed in format strings.
diff --git a/Misc/NEWS.d/next/Library/2022-07-03-16-26-35.gh-issue-78724.XNiJzf.rst b/Misc/NEWS.d/next/Library/2022-07-03-16-26-35.gh-issue-78724.XNiJzf.rst
new file mode 100644 (file)
index 0000000..9621e4d
--- /dev/null
@@ -0,0 +1 @@
+Fix crash in :class:`struct.Struct` when it was not completely initialized by initializing it in :meth:`~object.__new__``.  Patch by Kumar Aditya.
index 09f52a981485dda1029786ea00b8e55e5f9d1271..f9bac34c1e38b80b5795b8eb9751ed0bee6940c8 100644 (file)
@@ -1477,28 +1477,9 @@ prepare_s(PyStructObject *self)
     return -1;
 }
 
-static PyObject *
-s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyObject *self;
-
-    assert(type != NULL);
-    allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc);
-    assert(alloc_func != NULL);
-
-    self = alloc_func(type, 0);
-    if (self != NULL) {
-        PyStructObject *s = (PyStructObject*)self;
-        s->s_format = Py_NewRef(Py_None);
-        s->s_codes = NULL;
-        s->s_size = -1;
-        s->s_len = -1;
-    }
-    return self;
-}
-
 /*[clinic input]
-Struct.__init__
+@classmethod
+Struct.__new__
 
     format: object
 
@@ -1510,16 +1491,24 @@ the format string.
 See help(struct) for more on format strings.
 [clinic start generated code]*/
 
-static int
-Struct___init___impl(PyStructObject *self, PyObject *format)
-/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/
+static PyObject *
+Struct_impl(PyTypeObject *type, PyObject *format)
+/*[clinic end generated code: output=49468b044e334308 input=8b91868eb1df0e28]*/
 {
-    int ret = 0;
+    allocfunc alloc = PyType_GetSlot(type, Py_tp_alloc);
+    assert(alloc != NULL);
+    PyStructObject *self = (PyStructObject *)alloc(type, 0);
+
+    if (self == NULL) {
+        return NULL;
+    }
 
     if (PyUnicode_Check(format)) {
         format = PyUnicode_AsASCIIString(format);
-        if (format == NULL)
-            return -1;
+        if (format == NULL) {
+            Py_DECREF(self);
+            return NULL;
+        }
     }
     else {
         Py_INCREF(format);
@@ -1527,19 +1516,24 @@ Struct___init___impl(PyStructObject *self, PyObject *format)
 
     if (!PyBytes_Check(format)) {
         Py_DECREF(format);
+        Py_DECREF(self);
         PyErr_Format(PyExc_TypeError,
                      "Struct() argument 1 must be a str or bytes object, "
                      "not %.200s",
                      _PyType_Name(Py_TYPE(format)));
-        return -1;
+        return NULL;
     }
 
-    Py_SETREF(self->s_format, format);
+    self->s_format = format;
 
-    ret = prepare_s(self);
-    return ret;
+    if (prepare_s(self) < 0) {
+        Py_DECREF(self);
+        return NULL;
+    }
+    return (PyObject *)self;
 }
 
+
 static int
 s_clear(PyStructObject *s)
 {
@@ -2144,9 +2138,8 @@ static PyType_Slot PyStructType_slots[] = {
     {Py_tp_methods, s_methods},
     {Py_tp_members, s_members},
     {Py_tp_getset, s_getsetlist},
-    {Py_tp_init, Struct___init__},
+    {Py_tp_new, Struct},
     {Py_tp_alloc, PyType_GenericAlloc},
-    {Py_tp_new, s_new},
     {Py_tp_free, PyObject_GC_Del},
     {0, 0},
 };
index b21d9ff292433b01b4e8f7f30b4df2642976eec1..c3cf179ed4c040d62713e48ea81458663ea5963c 100644 (file)
@@ -8,7 +8,7 @@ preserve
 #endif
 
 
-PyDoc_STRVAR(Struct___init____doc__,
+PyDoc_STRVAR(Struct__doc__,
 "Struct(format)\n"
 "--\n"
 "\n"
@@ -19,13 +19,13 @@ PyDoc_STRVAR(Struct___init____doc__,
 "\n"
 "See help(struct) for more on format strings.");
 
-static int
-Struct___init___impl(PyStructObject *self, PyObject *format);
+static PyObject *
+Struct_impl(PyTypeObject *type, PyObject *format);
 
-static int
-Struct___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *
+Struct(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    int return_value = -1;
+    PyObject *return_value = NULL;
     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
 
     #define NUM_KEYWORDS 1
@@ -61,7 +61,7 @@ Struct___init__(PyObject *self, PyObject *args, PyObject *kwargs)
         goto exit;
     }
     format = fastargs[0];
-    return_value = Struct___init___impl((PyStructObject *)self, format);
+    return_value = Struct_impl(type, format);
 
 exit:
     return return_value;
@@ -451,4 +451,4 @@ exit:
 
     return return_value;
 }
-/*[clinic end generated code: output=eca7df0e75f8919d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f3d6e06f80368998 input=a9049054013a1b77]*/