[Python-checkins] bpo-42333: Port _ssl extension module to heap types (GH-23392)

tiran webhook-mailer at python.org
Fri Nov 20 03:40:16 EST 2020


https://github.com/python/cpython/commit/5c36da78d738d0e5fdb539a758cc15abc47c843b
commit: 5c36da78d738d0e5fdb539a758cc15abc47c843b
branch: master
author: Christian Heimes <christian at python.org>
committer: tiran <christian at python.org>
date: 2020-11-20T09:40:12+01:00
summary:

bpo-42333: Port _ssl extension module to heap types (GH-23392)

All types in _ssl module are now heap types.

files:
A Misc/NEWS.d/next/Library/2020-11-12-18-21-15.bpo-42333.J9vFmV.rst
M Modules/_ssl.c
M Modules/clinic/_ssl.c.h

diff --git a/Misc/NEWS.d/next/Library/2020-11-12-18-21-15.bpo-42333.J9vFmV.rst b/Misc/NEWS.d/next/Library/2020-11-12-18-21-15.bpo-42333.J9vFmV.rst
new file mode 100644
index 0000000000000..f8755c7685642
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-11-12-18-21-15.bpo-42333.J9vFmV.rst
@@ -0,0 +1 @@
+Port _ssl extension module to heap types.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index a34313b78543c..130dce40eec71 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -487,10 +487,10 @@ typedef struct {
     PySSLContext *ctx;
 } PySSLSession;
 
-static PyTypeObject PySSLContext_Type;
-static PyTypeObject PySSLSocket_Type;
-static PyTypeObject PySSLMemoryBIO_Type;
-static PyTypeObject PySSLSession_Type;
+static PyTypeObject *PySSLContext_Type;
+static PyTypeObject *PySSLSocket_Type;
+static PyTypeObject *PySSLMemoryBIO_Type;
+static PyTypeObject *PySSLSession_Type;
 
 static inline _PySSLError _PySSL_errno(int failed, const SSL *ssl, int retcode)
 {
@@ -508,12 +508,12 @@ static inline _PySSLError _PySSL_errno(int failed, const SSL *ssl, int retcode)
 
 /*[clinic input]
 module _ssl
-class _ssl._SSLContext "PySSLContext *" "&PySSLContext_Type"
-class _ssl._SSLSocket "PySSLSocket *" "&PySSLSocket_Type"
-class _ssl.MemoryBIO "PySSLMemoryBIO *" "&PySSLMemoryBIO_Type"
-class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type"
+class _ssl._SSLContext "PySSLContext *" "PySSLContext_Type"
+class _ssl._SSLSocket "PySSLSocket *" "PySSLSocket_Type"
+class _ssl.MemoryBIO "PySSLMemoryBIO *" "PySSLMemoryBIO_Type"
+class _ssl.SSLSession "PySSLSession *" "PySSLSession_Type"
 [clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdc67fafeeaa8109]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cc4883756da17954]*/
 
 #include "clinic/_ssl.c.h"
 
@@ -521,9 +521,9 @@ static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout);
 
 static int PySSL_set_owner(PySSLSocket *, PyObject *, void *);
 static int PySSL_set_session(PySSLSocket *, PyObject *, void *);
-#define PySSLSocket_Check(v)    Py_IS_TYPE(v, &PySSLSocket_Type)
-#define PySSLMemoryBIO_Check(v)    Py_IS_TYPE(v, &PySSLMemoryBIO_Type)
-#define PySSLSession_Check(v)   Py_IS_TYPE(v, &PySSLSession_Type)
+#define PySSLSocket_Check(v)    Py_IS_TYPE(v, PySSLSocket_Type)
+#define PySSLMemoryBIO_Check(v)    Py_IS_TYPE(v, PySSLMemoryBIO_Type)
+#define PySSLSession_Check(v)   Py_IS_TYPE(v, PySSLSession_Type)
 
 typedef enum {
     SOCKET_IS_NONBLOCKING,
@@ -587,7 +587,6 @@ SSLError_str(PyOSErrorObject *self)
 }
 
 static PyType_Slot sslerror_type_slots[] = {
-    {Py_tp_base, NULL},  /* Filled out in module init as it's not a constant */
     {Py_tp_doc, (void*)SSLError_doc},
     {Py_tp_str, SSLError_str},
     {0, 0},
@@ -937,7 +936,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
     SSL_CTX *ctx = sslctx->ctx;
     _PySSLError err = { 0 };
 
-    self = PyObject_New(PySSLSocket, &PySSLSocket_Type);
+    self = PyObject_New(PySSLSocket, PySSLSocket_Type);
     if (self == NULL)
         return NULL;
 
@@ -2194,7 +2193,7 @@ static PySSLContext *PySSL_get_context(PySSLSocket *self, void *closure) {
 static int PySSL_set_context(PySSLSocket *self, PyObject *value,
                                    void *closure) {
 
-    if (PyObject_TypeCheck(value, &PySSLContext_Type)) {
+    if (PyObject_TypeCheck(value, PySSLContext_Type)) {
 #if !HAVE_SNI
         PyErr_SetString(PyExc_NotImplementedError, "setting a socket's "
                         "context is not supported by your OpenSSL library");
@@ -2289,6 +2288,7 @@ PySSL_clear(PySSLSocket *self)
 static void
 PySSL_dealloc(PySSLSocket *self)
 {
+    PyTypeObject *tp = Py_TYPE(self);
     if (self->ssl)
         SSL_free(self->ssl);
     Py_XDECREF(self->Socket);
@@ -2296,6 +2296,7 @@ PySSL_dealloc(PySSLSocket *self)
     Py_XDECREF(self->server_hostname);
     Py_XDECREF(self->owner);
     PyObject_Del(self);
+    Py_DECREF(tp);
 }
 
 /* If the socket has a timeout, do a select()/poll() on the socket.
@@ -2895,7 +2896,7 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
         Py_RETURN_NONE;
     }
 #endif
-    pysess = PyObject_GC_New(PySSLSession, &PySSLSession_Type);
+    pysess = PyObject_GC_New(PySSLSession, PySSLSession_Type);
     if (pysess == NULL) {
         SSL_SESSION_free(session);
         return NULL;
@@ -3008,38 +3009,21 @@ static PyMethodDef PySSLMethods[] = {
     {NULL, NULL}
 };
 
-static PyTypeObject PySSLSocket_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_ssl._SSLSocket",                  /*tp_name*/
-    sizeof(PySSLSocket),                /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    /* methods */
-    (destructor)PySSL_dealloc,          /*tp_dealloc*/
-    0,                                  /*tp_vectorcall_offset*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    0,                                  /*tp_as_async*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    0,                                  /*tp_getattro*/
-    0,                                  /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,                 /*tp_flags*/
-    0,                                  /*tp_doc*/
-    (traverseproc) PySSL_traverse,      /*tp_traverse*/
-    (inquiry) PySSL_clear,              /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    0,                                  /*tp_weaklistoffset*/
-    0,                                  /*tp_iter*/
-    0,                                  /*tp_iternext*/
-    PySSLMethods,                       /*tp_methods*/
-    0,                                  /*tp_members*/
-    ssl_getsetlist,                     /*tp_getset*/
+static PyType_Slot PySSLSocket_slots[] = {
+    {Py_tp_methods, PySSLMethods},
+    {Py_tp_getset, ssl_getsetlist},
+    {Py_tp_dealloc, PySSL_dealloc},
+    {Py_tp_traverse, PySSL_traverse},
+    {Py_tp_clear, PySSL_clear},
+    {0, 0},
+};
+
+static PyType_Spec PySSLSocket_spec = {
+    "_ssl._SSLSocket",
+    sizeof(PySSLSocket),
+    0,
+    Py_TPFLAGS_DEFAULT,
+    PySSLSocket_slots,
 };
 
 
@@ -3316,6 +3300,7 @@ context_clear(PySSLContext *self)
 static void
 context_dealloc(PySSLContext *self)
 {
+    PyTypeObject *tp = Py_TYPE(self);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(self);
     context_clear(self);
@@ -3327,6 +3312,7 @@ context_dealloc(PySSLContext *self)
     PyMem_FREE(self->alpn_protocols);
 #endif
     Py_TYPE(self)->tp_free(self);
+    Py_DECREF(tp);
 }
 
 /*[clinic input]
@@ -4366,8 +4352,8 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock,
 
 /*[clinic input]
 _ssl._SSLContext._wrap_bio
-    incoming: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *")
-    outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *")
+    incoming: object(subclass_of="PySSLMemoryBIO_Type", type="PySSLMemoryBIO *")
+    outgoing: object(subclass_of="PySSLMemoryBIO_Type", type="PySSLMemoryBIO *")
     server_side: int
     server_hostname as hostname_obj: object = None
     *
@@ -4381,7 +4367,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming,
                                 PySSLMemoryBIO *outgoing, int server_side,
                                 PyObject *hostname_obj, PyObject *owner,
                                 PyObject *session)
-/*[clinic end generated code: output=5c5d6d9b41f99332 input=8cf22f4d586ac56a]*/
+/*[clinic end generated code: output=5c5d6d9b41f99332 input=63867b8f3e1a1aa3]*/
 {
     char *hostname = NULL;
     PyObject *res;
@@ -4829,45 +4815,22 @@ static struct PyMethodDef context_methods[] = {
     {NULL, NULL}        /* sentinel */
 };
 
-static PyTypeObject PySSLContext_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_ssl._SSLContext",                        /*tp_name*/
-    sizeof(PySSLContext),                      /*tp_basicsize*/
-    0,                                         /*tp_itemsize*/
-    (destructor)context_dealloc,               /*tp_dealloc*/
-    0,                                         /*tp_vectorcall_offset*/
-    0,                                         /*tp_getattr*/
-    0,                                         /*tp_setattr*/
-    0,                                         /*tp_as_async*/
-    0,                                         /*tp_repr*/
-    0,                                         /*tp_as_number*/
-    0,                                         /*tp_as_sequence*/
-    0,                                         /*tp_as_mapping*/
-    0,                                         /*tp_hash*/
-    0,                                         /*tp_call*/
-    0,                                         /*tp_str*/
-    0,                                         /*tp_getattro*/
-    0,                                         /*tp_setattro*/
-    0,                                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
-    0,                                         /*tp_doc*/
-    (traverseproc) context_traverse,           /*tp_traverse*/
-    (inquiry) context_clear,                   /*tp_clear*/
-    0,                                         /*tp_richcompare*/
-    0,                                         /*tp_weaklistoffset*/
-    0,                                         /*tp_iter*/
-    0,                                         /*tp_iternext*/
-    context_methods,                           /*tp_methods*/
-    0,                                         /*tp_members*/
-    context_getsetlist,                        /*tp_getset*/
-    0,                                         /*tp_base*/
-    0,                                         /*tp_dict*/
-    0,                                         /*tp_descr_get*/
-    0,                                         /*tp_descr_set*/
-    0,                                         /*tp_dictoffset*/
-    0,                                         /*tp_init*/
-    0,                                         /*tp_alloc*/
-    _ssl__SSLContext,                          /*tp_new*/
+static PyType_Slot PySSLContext_slots[] = {
+    {Py_tp_methods, context_methods},
+    {Py_tp_getset, context_getsetlist},
+    {Py_tp_new, _ssl__SSLContext},
+    {Py_tp_dealloc, context_dealloc},
+    {Py_tp_traverse, context_traverse},
+    {Py_tp_clear, context_clear},
+    {0, 0},
+};
+
+static PyType_Spec PySSLContext_spec = {
+    "_ssl._SSLContext",
+    sizeof(PySSLContext),
+    0,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+    PySSLContext_slots,
 };
 
 
@@ -4915,8 +4878,10 @@ _ssl_MemoryBIO_impl(PyTypeObject *type)
 static void
 memory_bio_dealloc(PySSLMemoryBIO *self)
 {
+    PyTypeObject *tp = Py_TYPE(self);
     BIO_free(self->bio);
     Py_TYPE(self)->tp_free(self);
+    Py_DECREF(tp);
 }
 
 static PyObject *
@@ -5054,47 +5019,21 @@ static struct PyMethodDef memory_bio_methods[] = {
     {NULL, NULL}        /* sentinel */
 };
 
-static PyTypeObject PySSLMemoryBIO_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_ssl.MemoryBIO",                         /*tp_name*/
-    sizeof(PySSLMemoryBIO),                    /*tp_basicsize*/
-    0,                                         /*tp_itemsize*/
-    (destructor)memory_bio_dealloc,            /*tp_dealloc*/
-    0,                                         /*tp_vectorcall_offset*/
-    0,                                         /*tp_getattr*/
-    0,                                         /*tp_setattr*/
-    0,                                         /*tp_as_async*/
-    0,                                         /*tp_repr*/
-    0,                                         /*tp_as_number*/
-    0,                                         /*tp_as_sequence*/
-    0,                                         /*tp_as_mapping*/
-    0,                                         /*tp_hash*/
-    0,                                         /*tp_call*/
-    0,                                         /*tp_str*/
-    0,                                         /*tp_getattro*/
-    0,                                         /*tp_setattro*/
-    0,                                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,                        /*tp_flags*/
-    0,                                         /*tp_doc*/
-    0,                                         /*tp_traverse*/
-    0,                                         /*tp_clear*/
-    0,                                         /*tp_richcompare*/
-    0,                                         /*tp_weaklistoffset*/
-    0,                                         /*tp_iter*/
-    0,                                         /*tp_iternext*/
-    memory_bio_methods,                        /*tp_methods*/
-    0,                                         /*tp_members*/
-    memory_bio_getsetlist,                     /*tp_getset*/
-    0,                                         /*tp_base*/
-    0,                                         /*tp_dict*/
-    0,                                         /*tp_descr_get*/
-    0,                                         /*tp_descr_set*/
-    0,                                         /*tp_dictoffset*/
-    0,                                         /*tp_init*/
-    0,                                         /*tp_alloc*/
-    _ssl_MemoryBIO,                            /*tp_new*/
+static PyType_Slot PySSLMemoryBIO_slots[] = {
+    {Py_tp_methods, memory_bio_methods},
+    {Py_tp_getset, memory_bio_getsetlist},
+    {Py_tp_new, _ssl_MemoryBIO},
+    {Py_tp_dealloc, memory_bio_dealloc},
+    {0, 0},
 };
 
+static PyType_Spec PySSLMemoryBIO_spec = {
+    "_ssl.MemoryBIO",
+    sizeof(PySSLMemoryBIO),
+    0,
+    Py_TPFLAGS_DEFAULT,
+    PySSLMemoryBIO_slots,
+};
 
 /*
  * SSL Session object
@@ -5103,6 +5042,7 @@ static PyTypeObject PySSLMemoryBIO_Type = {
 static void
 PySSLSession_dealloc(PySSLSession *self)
 {
+    PyTypeObject *tp = Py_TYPE(self);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(self);
     Py_XDECREF(self->ctx);
@@ -5110,6 +5050,7 @@ PySSLSession_dealloc(PySSLSession *self)
         SSL_SESSION_free(self->session);
     }
     PyObject_GC_Del(self);
+    Py_DECREF(tp);
 }
 
 static PyObject *
@@ -5251,37 +5192,21 @@ static PyGetSetDef PySSLSession_getsetlist[] = {
     {NULL},            /* sentinel */
 };
 
-static PyTypeObject PySSLSession_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_ssl.Session",                            /*tp_name*/
-    sizeof(PySSLSession),                      /*tp_basicsize*/
-    0,                                         /*tp_itemsize*/
-    (destructor)PySSLSession_dealloc,          /*tp_dealloc*/
-    0,                                         /*tp_vectorcall_offset*/
-    0,                                         /*tp_getattr*/
-    0,                                         /*tp_setattr*/
-    0,                                         /*tp_as_async*/
-    0,                                         /*tp_repr*/
-    0,                                         /*tp_as_number*/
-    0,                                         /*tp_as_sequence*/
-    0,                                         /*tp_as_mapping*/
-    0,                                         /*tp_hash*/
-    0,                                         /*tp_call*/
-    0,                                         /*tp_str*/
-    0,                                         /*tp_getattro*/
-    0,                                         /*tp_setattro*/
-    0,                                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
-    0,                                         /*tp_doc*/
-    (traverseproc)PySSLSession_traverse,       /*tp_traverse*/
-    (inquiry)PySSLSession_clear,               /*tp_clear*/
-    PySSLSession_richcompare,                  /*tp_richcompare*/
-    0,                                         /*tp_weaklistoffset*/
-    0,                                         /*tp_iter*/
-    0,                                         /*tp_iternext*/
-    0,                                         /*tp_methods*/
-    0,                                         /*tp_members*/
-    PySSLSession_getsetlist,                   /*tp_getset*/
+static PyType_Slot PySSLSession_slots[] = {
+    {Py_tp_getset,PySSLSession_getsetlist},
+    {Py_tp_richcompare, PySSLSession_richcompare},
+    {Py_tp_dealloc, PySSLSession_dealloc},
+    {Py_tp_traverse, PySSLSession_traverse},
+    {Py_tp_clear, PySSLSession_clear},
+    {0, 0},
+};
+
+static PyType_Spec PySSLSession_spec = {
+    "_ssl.SSLSession",
+    sizeof(PySSLSession),
+    0,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+    PySSLSession_slots,
 };
 
 
@@ -5979,23 +5904,195 @@ static int _setup_ssl_threads(void) {
 
 #endif  /* HAVE_OPENSSL_CRYPTO_LOCK for OpenSSL < 1.1.0 */
 
-PyDoc_STRVAR(module_doc,
-"Implementation module for SSL socket operations.  See the socket module\n\
-for documentation.");
+static int
+sslmodule_init_types(PyObject *module)
+{
+    PySSLContext_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &PySSLContext_spec, NULL
+    );
+    if (PySSLContext_Type == NULL)
+        return -1;
 
+    PySSLSocket_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &PySSLSocket_spec, NULL
+    );
+    if (PySSLSocket_Type == NULL)
+        return -1;
 
-static struct PyModuleDef _sslmodule = {
-    PyModuleDef_HEAD_INIT,
-    "_ssl",
-    module_doc,
-    -1,
-    PySSL_methods,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
+    PySSLMemoryBIO_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &PySSLMemoryBIO_spec, NULL
+    );
+    if (PySSLMemoryBIO_Type == NULL)
+        return -1;
 
+    PySSLSession_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &PySSLSession_spec, NULL
+    );
+    if (PySSLSession_Type == NULL)
+        return -1;
+
+    if (PyModule_AddType(module, PySSLContext_Type))
+        return -1;
+    if (PyModule_AddType(module, PySSLSocket_Type))
+        return -1;
+    if (PyModule_AddType(module, PySSLMemoryBIO_Type))
+        return -1;
+    if (PyModule_AddType(module, PySSLSession_Type))
+        return -1;
+
+    return 0;
+}
+
+static int
+sslmodule_init_exceptions(PyObject *module)
+{
+    PyObject *bases = NULL;
+
+#define add_exception(exc, name, doc, base)                               \
+do {                                                                      \
+    (exc) = PyErr_NewExceptionWithDoc("ssl." name, (doc), (base), NULL);  \
+    if ((exc) == NULL) goto error;                                        \
+    if (PyModule_AddObjectRef(module, name, exc) < 0) goto error;         \
+} while(0)
+
+    bases = PyTuple_Pack(1, PyExc_OSError);
+    if (bases == NULL) {
+        goto error;
+    }
+    PySSLErrorObject = PyType_FromSpecWithBases(&sslerror_type_spec, bases);
+    Py_CLEAR(bases);
+    if (PySSLErrorObject == NULL) {
+        goto error;
+    }
+    if (PyModule_AddObjectRef(module, "SSLError", PySSLErrorObject) < 0) {
+        goto error;
+    }
+
+    /* ssl.CertificateError used to be a subclass of ValueError */
+    bases = PyTuple_Pack(2, PySSLErrorObject, PyExc_ValueError);
+    if (bases == NULL) {
+        goto error;
+    }
+    add_exception(
+        PySSLCertVerificationErrorObject,
+        "SSLCertVerificationError",
+        SSLCertVerificationError_doc,
+        bases
+    );
+    Py_CLEAR(bases);
+
+    add_exception(
+        PySSLZeroReturnErrorObject,
+        "SSLZeroReturnError",
+        SSLZeroReturnError_doc,
+        PySSLErrorObject
+    );
+
+    add_exception(
+        PySSLWantWriteErrorObject,
+        "SSLWantWriteError",
+        SSLWantWriteError_doc,
+        PySSLErrorObject
+    );
+
+    add_exception(
+        PySSLWantReadErrorObject,
+        "SSLWantReadError",
+        SSLWantReadError_doc,
+        PySSLErrorObject
+    );
+
+    add_exception(
+        PySSLSyscallErrorObject,
+        "SSLSyscallError",
+        SSLSyscallError_doc,
+        PySSLErrorObject
+    );
+
+    add_exception(
+        PySSLEOFErrorObject,
+        "SSLEOFError",
+        SSLEOFError_doc,
+        PySSLErrorObject
+    );
+#undef add_exception
+
+    return 0;
+  error:
+    Py_XDECREF(bases);
+    return -1;
+}
+
+static int
+sslmodule_init_socketapi(PyObject *module)
+{
+    PySocketModule_APIObject *socket_api;
+
+    /* Load _socket module and its C API */
+    socket_api = PySocketModule_ImportModuleAndAPI();
+    if (socket_api == NULL)
+        return -1;
+    PySocketModule = *socket_api;
+
+    return 0;
+}
+
+static int
+sslmodule_init_errorcodes(PyObject *module)
+{
+    struct py_ssl_error_code *errcode;
+    struct py_ssl_library_code *libcode;
+
+    /* Mappings for error codes */
+    err_codes_to_names = PyDict_New();
+    if (err_codes_to_names == NULL)
+        return -1;
+    err_names_to_codes = PyDict_New();
+    if (err_names_to_codes == NULL)
+        return -1;
+    lib_codes_to_names = PyDict_New();
+    if (lib_codes_to_names == NULL)
+        return -1;
+
+    errcode = error_codes;
+    while (errcode->mnemonic != NULL) {
+        PyObject *mnemo, *key;
+        mnemo = PyUnicode_FromString(errcode->mnemonic);
+        key = Py_BuildValue("ii", errcode->library, errcode->reason);
+        if (mnemo == NULL || key == NULL)
+            return -1;
+        if (PyDict_SetItem(err_codes_to_names, key, mnemo))
+            return -1;
+        if (PyDict_SetItem(err_names_to_codes, mnemo, key))
+            return -1;
+        Py_DECREF(key);
+        Py_DECREF(mnemo);
+        errcode++;
+    }
+
+    libcode = library_codes;
+    while (libcode->library != NULL) {
+        PyObject *mnemo, *key;
+        key = PyLong_FromLong(libcode->code);
+        mnemo = PyUnicode_FromString(libcode->library);
+        if (key == NULL || mnemo == NULL)
+            return -1;
+        if (PyDict_SetItem(lib_codes_to_names, key, mnemo))
+            return -1;
+        Py_DECREF(key);
+        Py_DECREF(mnemo);
+        libcode++;
+    }
+
+    if (PyModule_AddObject(module, "err_codes_to_names", err_codes_to_names))
+        return -1;
+    if (PyModule_AddObject(module, "err_names_to_codes", err_names_to_codes))
+        return -1;
+    if (PyModule_AddObject(module, "lib_codes_to_names", lib_codes_to_names))
+        return -1;
+
+    return 0;
+}
 
 static void
 parse_openssl_version(unsigned long libver,
@@ -6014,113 +6111,43 @@ parse_openssl_version(unsigned long libver,
     *major = libver & 0xFF;
 }
 
-PyMODINIT_FUNC
-PyInit__ssl(void)
+static int
+sslmodule_init_versioninfo(PyObject *m)
 {
-    PyObject *m, *d, *r, *bases;
+    PyObject *r;
     unsigned long libver;
     unsigned int major, minor, fix, patch, status;
-    PySocketModule_APIObject *socket_api;
-    struct py_ssl_error_code *errcode;
-    struct py_ssl_library_code *libcode;
-
-    if (PyType_Ready(&PySSLContext_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&PySSLSocket_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&PySSLMemoryBIO_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&PySSLSession_Type) < 0)
-        return NULL;
-
 
-    m = PyModule_Create(&_sslmodule);
-    if (m == NULL)
-        return NULL;
-    d = PyModule_GetDict(m);
-
-    /* Load _socket module and its C API */
-    socket_api = PySocketModule_ImportModuleAndAPI();
-    if (!socket_api)
-        return NULL;
-    PySocketModule = *socket_api;
+    /* OpenSSL version */
+    /* SSLeay() gives us the version of the library linked against,
+       which could be different from the headers version.
+    */
+    libver = OpenSSL_version_num();
+    r = PyLong_FromUnsignedLong(libver);
+    if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r))
+        return -1;
 
-#ifndef OPENSSL_VERSION_1_1
-    /* Load all algorithms and initialize cpuid */
-    OPENSSL_add_all_algorithms_noconf();
-    /* Init OpenSSL */
-    SSL_load_error_strings();
-    SSL_library_init();
-#endif
+    parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
+    r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
+    if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r))
+        return -1;
 
-#ifdef HAVE_OPENSSL_CRYPTO_LOCK
-    /* note that this will start threading if not already started */
-    if (!_setup_ssl_threads()) {
-        return NULL;
-    }
-#elif OPENSSL_VERSION_1_1
-    /* OpenSSL 1.1.0 builtin thread support is enabled */
-    _ssl_locks_count++;
-#endif
+    r = PyUnicode_FromString(OpenSSL_version(OPENSSL_VERSION));
+    if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r))
+        return -1;
 
-    /* Add symbols to module dict */
-    sslerror_type_slots[0].pfunc = PyExc_OSError;
-    PySSLErrorObject = PyType_FromSpec(&sslerror_type_spec);
-    if (PySSLErrorObject == NULL)
-        return NULL;
+    libver = OPENSSL_VERSION_NUMBER;
+    parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
+    r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
+    if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r))
+        return -1;
 
-    /* ssl.CertificateError used to be a subclass of ValueError */
-    bases = Py_BuildValue("OO", PySSLErrorObject, PyExc_ValueError);
-    if (bases == NULL)
-        return NULL;
-    PySSLCertVerificationErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLCertVerificationError", SSLCertVerificationError_doc,
-        bases, NULL);
-    Py_DECREF(bases);
-    PySSLZeroReturnErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLZeroReturnError", SSLZeroReturnError_doc,
-        PySSLErrorObject, NULL);
-    PySSLWantReadErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLWantReadError", SSLWantReadError_doc,
-        PySSLErrorObject, NULL);
-    PySSLWantWriteErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLWantWriteError", SSLWantWriteError_doc,
-        PySSLErrorObject, NULL);
-    PySSLSyscallErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLSyscallError", SSLSyscallError_doc,
-        PySSLErrorObject, NULL);
-    PySSLEOFErrorObject = PyErr_NewExceptionWithDoc(
-        "ssl.SSLEOFError", SSLEOFError_doc,
-        PySSLErrorObject, NULL);
-    if (PySSLCertVerificationErrorObject == NULL
-        || PySSLZeroReturnErrorObject == NULL
-        || PySSLWantReadErrorObject == NULL
-        || PySSLWantWriteErrorObject == NULL
-        || PySSLSyscallErrorObject == NULL
-        || PySSLEOFErrorObject == NULL)
-        return NULL;
-    if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLCertVerificationError",
-                                PySSLCertVerificationErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLZeroReturnError", PySSLZeroReturnErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLWantReadError", PySSLWantReadErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLWantWriteError", PySSLWantWriteErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLSyscallError", PySSLSyscallErrorObject) != 0
-        || PyDict_SetItemString(d, "SSLEOFError", PySSLEOFErrorObject) != 0)
-        return NULL;
-    if (PyDict_SetItemString(d, "_SSLContext",
-                             (PyObject *)&PySSLContext_Type) != 0)
-        return NULL;
-    if (PyDict_SetItemString(d, "_SSLSocket",
-                             (PyObject *)&PySSLSocket_Type) != 0)
-        return NULL;
-    if (PyDict_SetItemString(d, "MemoryBIO",
-                             (PyObject *)&PySSLMemoryBIO_Type) != 0)
-        return NULL;
-    if (PyDict_SetItemString(d, "SSLSession",
-                             (PyObject *)&PySSLSession_Type) != 0)
-        return NULL;
+    return 0;
+}
 
+static int
+sslmodule_init_constants(PyObject *m)
+{
     PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS",
                                PY_SSL_DEFAULT_CIPHER_STRING);
 
@@ -6377,72 +6404,71 @@ PyInit__ssl(void)
     addbool(m, "HAS_TLSv1_3", 0);
 #endif
 
-    /* Mappings for error codes */
-    err_codes_to_names = PyDict_New();
-    err_names_to_codes = PyDict_New();
-    if (err_codes_to_names == NULL || err_names_to_codes == NULL)
+    return 0;
+}
+
+static int
+sslmodule_legacy(PyObject *module)
+{
+#ifndef OPENSSL_VERSION_1_1
+    /* Load all algorithms and initialize cpuid */
+    OPENSSL_add_all_algorithms_noconf();
+    /* Init OpenSSL */
+    SSL_load_error_strings();
+    SSL_library_init();
+#endif
+
+#ifdef HAVE_OPENSSL_CRYPTO_LOCK
+    /* note that this will start threading if not already started */
+    if (!_setup_ssl_threads()) {
         return NULL;
-    errcode = error_codes;
-    while (errcode->mnemonic != NULL) {
-        PyObject *mnemo, *key;
-        mnemo = PyUnicode_FromString(errcode->mnemonic);
-        key = Py_BuildValue("ii", errcode->library, errcode->reason);
-        if (mnemo == NULL || key == NULL)
-            return NULL;
-        if (PyDict_SetItem(err_codes_to_names, key, mnemo))
-            return NULL;
-        if (PyDict_SetItem(err_names_to_codes, mnemo, key))
-            return NULL;
-        Py_DECREF(key);
-        Py_DECREF(mnemo);
-        errcode++;
     }
-    if (PyModule_AddObject(m, "err_codes_to_names", err_codes_to_names))
-        return NULL;
-    if (PyModule_AddObject(m, "err_names_to_codes", err_names_to_codes))
+#elif OPENSSL_VERSION_1_1
+    /* OpenSSL 1.1.0 builtin thread support is enabled */
+    _ssl_locks_count++;
+#endif
+    return 0;
+}
+
+PyDoc_STRVAR(module_doc,
+"Implementation module for SSL socket operations.  See the socket module\n\
+for documentation.");
+
+
+static struct PyModuleDef _sslmodule = {
+    PyModuleDef_HEAD_INIT,
+    "_ssl",
+    module_doc,
+    -1,
+    PySSL_methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+PyMODINIT_FUNC
+PyInit__ssl(void)
+{
+    PyObject *m;
+
+    m = PyModule_Create(&_sslmodule);
+    if (m == NULL)
         return NULL;
 
-    lib_codes_to_names = PyDict_New();
-    if (lib_codes_to_names == NULL)
+    if (sslmodule_init_types(m) != 0)
         return NULL;
-    libcode = library_codes;
-    while (libcode->library != NULL) {
-        PyObject *mnemo, *key;
-        key = PyLong_FromLong(libcode->code);
-        mnemo = PyUnicode_FromString(libcode->library);
-        if (key == NULL || mnemo == NULL)
-            return NULL;
-        if (PyDict_SetItem(lib_codes_to_names, key, mnemo))
-            return NULL;
-        Py_DECREF(key);
-        Py_DECREF(mnemo);
-        libcode++;
-    }
-    if (PyModule_AddObject(m, "lib_codes_to_names", lib_codes_to_names))
+    if (sslmodule_init_exceptions(m) != 0)
         return NULL;
-
-    /* OpenSSL version */
-    /* SSLeay() gives us the version of the library linked against,
-       which could be different from the headers version.
-    */
-    libver = OpenSSL_version_num();
-    r = PyLong_FromUnsignedLong(libver);
-    if (r == NULL)
+    if (sslmodule_init_socketapi(m) != 0)
         return NULL;
-    if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r))
+    if (sslmodule_init_errorcodes(m) != 0)
         return NULL;
-    parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
-    r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
-    if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r))
+    if (sslmodule_init_constants(m) != 0)
         return NULL;
-    r = PyUnicode_FromString(OpenSSL_version(OPENSSL_VERSION));
-    if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r))
+    if (sslmodule_init_versioninfo(m) != 0)
         return NULL;
-
-    libver = OPENSSL_VERSION_NUMBER;
-    parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
-    r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
-    if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r))
+    if (sslmodule_legacy(m) != 0)
         return NULL;
 
     return m;
diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h
index 2375f83b325c7..43469d3c35824 100644
--- a/Modules/clinic/_ssl.c.h
+++ b/Modules/clinic/_ssl.c.h
@@ -399,7 +399,7 @@ _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     PyObject *return_value = NULL;
     int proto_version;
 
-    if ((type == &PySSLContext_Type) &&
+    if ((type == PySSLContext_Type) &&
         !_PyArg_NoKeywords("_SSLContext", kwargs)) {
         goto exit;
     }
@@ -754,13 +754,13 @@ _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t
     if (!args) {
         goto exit;
     }
-    if (!PyObject_TypeCheck(args[0], &PySSLMemoryBIO_Type)) {
-        _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (&PySSLMemoryBIO_Type)->tp_name, args[0]);
+    if (!PyObject_TypeCheck(args[0], PySSLMemoryBIO_Type)) {
+        _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (PySSLMemoryBIO_Type)->tp_name, args[0]);
         goto exit;
     }
     incoming = (PySSLMemoryBIO *)args[0];
-    if (!PyObject_TypeCheck(args[1], &PySSLMemoryBIO_Type)) {
-        _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (&PySSLMemoryBIO_Type)->tp_name, args[1]);
+    if (!PyObject_TypeCheck(args[1], PySSLMemoryBIO_Type)) {
+        _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (PySSLMemoryBIO_Type)->tp_name, args[1]);
         goto exit;
     }
     outgoing = (PySSLMemoryBIO *)args[1];
@@ -919,11 +919,11 @@ _ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
 
-    if ((type == &PySSLMemoryBIO_Type) &&
+    if ((type == PySSLMemoryBIO_Type) &&
         !_PyArg_NoPositional("MemoryBIO", args)) {
         goto exit;
     }
-    if ((type == &PySSLMemoryBIO_Type) &&
+    if ((type == PySSLMemoryBIO_Type) &&
         !_PyArg_NoKeywords("MemoryBIO", kwargs)) {
         goto exit;
     }
@@ -1447,4 +1447,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
 #ifndef _SSL_ENUM_CRLS_METHODDEF
     #define _SSL_ENUM_CRLS_METHODDEF
 #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */
-/*[clinic end generated code: output=d4e4f9cdd08819f4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2bb53a80040c9b35 input=a9049054013a1b77]*/



More information about the Python-checkins mailing list