https://github.com/python/cpython/commit/e708ac8dd4c6c6ceece70511ddaad7b34422e4e0
commit: e708ac8dd4c6c6ceece70511ddaad7b34422e4e0
branch: main
author: Bénédikt Tran <10796600+picn...@users.noreply.github.com>
committer: encukou <encu...@gmail.com>
date: 2025-03-17T16:25:28+01:00
summary:

gh-111178: fix UBSan failures in `Modules/_ssl.c` (GH-130719)

* fix UBSan failures for `PySSLContext`, `PySSLSocket`, `PySSLMemoryBIO`, 
`PySSLSession`

files:
M Modules/_ssl.c
M Modules/_ssl/cert.c
M Modules/_ssl/debughelpers.c

diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 85e917fbbb7093..af67e980dd7933 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -312,6 +312,8 @@ typedef struct {
 #endif
 } PySSLContext;
 
+#define PySSLContext_CAST(op)   ((PySSLContext *)(op))
+
 typedef struct {
     int ssl; /* last seen error from SSL */
     int c; /* last seen error from libc */
@@ -337,18 +339,24 @@ typedef struct {
     PyObject *exc;
 } PySSLSocket;
 
+#define PySSLSocket_CAST(op)    ((PySSLSocket *)(op))
+
 typedef struct {
     PyObject_HEAD
     BIO *bio;
     int eof_written;
 } PySSLMemoryBIO;
 
+#define PySSLMemoryBIO_CAST(op) ((PySSLMemoryBIO *)(op))
+
 typedef struct {
     PyObject_HEAD
     SSL_SESSION *session;
     PySSLContext *ctx;
 } PySSLSession;
 
+#define PySSLSession_CAST(op)   ((PySSLSession *)(op))
+
 static inline _PySSLError _PySSL_errno(int failed, const SSL *ssl, int retcode)
 {
     _PySSLError err = { 0 };
@@ -2317,23 +2325,26 @@ _ssl__SSLSocket_owner_set_impl(PySSLSocket *self, 
PyObject *value)
 }
 
 static int
-PySSL_traverse(PySSLSocket *self, visitproc visit, void *arg)
+PySSL_traverse(PyObject *op, visitproc visit, void *arg)
 {
+    PySSLSocket *self = PySSLSocket_CAST(op);
     Py_VISIT(self->exc);
     Py_VISIT(Py_TYPE(self));
     return 0;
 }
 
 static int
-PySSL_clear(PySSLSocket *self)
+PySSL_clear(PyObject *op)
 {
+    PySSLSocket *self = PySSLSocket_CAST(op);
     Py_CLEAR(self->exc);
     return 0;
 }
 
 static void
-PySSL_dealloc(PySSLSocket *self)
+PySSL_dealloc(PyObject *op)
 {
+    PySSLSocket *self = PySSLSocket_CAST(op);
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
     if (self->ssl) {
@@ -3278,8 +3289,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int 
proto_version)
 }
 
 static int
-context_traverse(PySSLContext *self, visitproc visit, void *arg)
+context_traverse(PyObject *op, visitproc visit, void *arg)
 {
+    PySSLContext *self = PySSLContext_CAST(op);
     Py_VISIT(self->set_sni_cb);
     Py_VISIT(self->msg_cb);
     Py_VISIT(Py_TYPE(self));
@@ -3287,8 +3299,9 @@ context_traverse(PySSLContext *self, visitproc visit, 
void *arg)
 }
 
 static int
-context_clear(PySSLContext *self)
+context_clear(PyObject *op)
 {
+    PySSLContext *self = PySSLContext_CAST(op);
     Py_CLEAR(self->set_sni_cb);
     Py_CLEAR(self->msg_cb);
     Py_CLEAR(self->keylog_filename);
@@ -3306,15 +3319,16 @@ context_clear(PySSLContext *self)
 }
 
 static void
-context_dealloc(PySSLContext *self)
+context_dealloc(PyObject *op)
 {
+    PySSLContext *self = PySSLContext_CAST(op);
     PyTypeObject *tp = Py_TYPE(self);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(self);
-    context_clear(self);
+    (void)context_clear(op);
     SSL_CTX_free(self->ctx);
     PyMem_FREE(self->alpn_protocols);
-    Py_TYPE(self)->tp_free(self);
+    tp->tp_free(self);
     Py_DECREF(tp);
 }
 
@@ -3908,7 +3922,9 @@ _ssl__SSLContext_check_hostname_set_impl(PySSLContext 
*self, PyObject *value)
 }
 
 static PyObject *
-get_post_handshake_auth(PySSLContext *self, void *c) {
+get_post_handshake_auth(PyObject *op, void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
 #if defined(PySSL_HAVE_POST_HS_AUTH)
     return PyBool_FromLong(self->post_handshake_auth);
 #else
@@ -3918,7 +3934,9 @@ get_post_handshake_auth(PySSLContext *self, void *c) {
 
 #if defined(PySSL_HAVE_POST_HS_AUTH)
 static int
-set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) {
+set_post_handshake_auth(PyObject *op, PyObject *arg, void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
     if (arg == NULL) {
         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
         return -1;
@@ -5197,18 +5215,18 @@ static PyGetSetDef context_getsetlist[] = {
     _SSL__SSLCONTEXT__HOST_FLAGS_GETSETDEF
     _SSL__SSLCONTEXT_MINIMUM_VERSION_GETSETDEF
     _SSL__SSLCONTEXT_MAXIMUM_VERSION_GETSETDEF
-    {"keylog_filename", (getter) _PySSLContext_get_keylog_filename,
-                        (setter) _PySSLContext_set_keylog_filename, NULL},
-    {"_msg_callback", (getter) _PySSLContext_get_msg_callback,
-                      (setter) _PySSLContext_set_msg_callback, NULL},
+    {"keylog_filename", _PySSLContext_get_keylog_filename,
+                        _PySSLContext_set_keylog_filename, NULL},
+    {"_msg_callback", _PySSLContext_get_msg_callback,
+                      _PySSLContext_set_msg_callback, NULL},
     _SSL__SSLCONTEXT_SNI_CALLBACK_GETSETDEF
 #if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3)
     _SSL__SSLCONTEXT_NUM_TICKETS_GETSETDEF
 #endif
     _SSL__SSLCONTEXT_OPTIONS_GETSETDEF
-    {"post_handshake_auth", (getter) get_post_handshake_auth,
+    {"post_handshake_auth", get_post_handshake_auth,
 #if defined(PySSL_HAVE_POST_HS_AUTH)
-                            (setter) set_post_handshake_auth,
+                            set_post_handshake_auth,
 #else
                             NULL,
 #endif
@@ -5300,19 +5318,20 @@ _ssl_MemoryBIO_impl(PyTypeObject *type)
 }
 
 static int
-memory_bio_traverse(PySSLMemoryBIO *self, visitproc visit, void *arg)
+memory_bio_traverse(PyObject *self, visitproc visit, void *arg)
 {
     Py_VISIT(Py_TYPE(self));
     return 0;
 }
 
 static void
-memory_bio_dealloc(PySSLMemoryBIO *self)
+memory_bio_dealloc(PyObject *op)
 {
+    PySSLMemoryBIO *self = PySSLMemoryBIO_CAST(op);
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
-    BIO_free(self->bio);
-    Py_TYPE(self)->tp_free(self);
+    (void)BIO_free(self->bio);
+    tp->tp_free(self);
     Py_DECREF(tp);
 }
 
@@ -5492,8 +5511,9 @@ static PyType_Spec PySSLMemoryBIO_spec = {
  */
 
 static void
-PySSLSession_dealloc(PySSLSession *self)
+PySSLSession_dealloc(PyObject *op)
 {
+    PySSLSession *self = PySSLSession_CAST(op);
     PyTypeObject *tp = Py_TYPE(self);
     /* bpo-31095: UnTrack is needed before calling any callbacks */
     PyObject_GC_UnTrack(self);
@@ -5514,7 +5534,7 @@ PySSLSession_richcompare(PyObject *left, PyObject *right, 
int op)
     }
 
     int result;
-    PyTypeObject *sesstype = 
((PySSLSession*)left)->ctx->state->PySSLSession_Type;
+    PyTypeObject *sesstype = 
PySSLSession_CAST(left)->ctx->state->PySSLSession_Type;
 
     if (!Py_IS_TYPE(left, sesstype) || !Py_IS_TYPE(right, sesstype)) {
         Py_RETURN_NOTIMPLEMENTED;
@@ -5525,9 +5545,9 @@ PySSLSession_richcompare(PyObject *left, PyObject *right, 
int op)
     } else {
         const unsigned char *left_id, *right_id;
         unsigned int left_len, right_len;
-        left_id = SSL_SESSION_get_id(((PySSLSession *)left)->session,
+        left_id = SSL_SESSION_get_id(PySSLSession_CAST(left)->session,
                                      &left_len);
-        right_id = SSL_SESSION_get_id(((PySSLSession *)right)->session,
+        right_id = SSL_SESSION_get_id(PySSLSession_CAST(right)->session,
                                       &right_len);
         if (left_len == right_len) {
             result = memcmp(left_id, right_id, left_len);
@@ -5564,16 +5584,18 @@ PySSLSession_richcompare(PyObject *left, PyObject 
*right, int op)
 }
 
 static int
-PySSLSession_traverse(PySSLSession *self, visitproc visit, void *arg)
+PySSLSession_traverse(PyObject *op, visitproc visit, void *arg)
 {
+    PySSLSession *self = PySSLSession_CAST(op);
     Py_VISIT(self->ctx);
     Py_VISIT(Py_TYPE(self));
     return 0;
 }
 
 static int
-PySSLSession_clear(PySSLSession *self)
+PySSLSession_clear(PyObject *op)
 {
+    PySSLSession *self = PySSLSession_CAST(op);
     Py_CLEAR(self->ctx);
     return 0;
 }
diff --git a/Modules/_ssl/cert.c b/Modules/_ssl/cert.c
index c11ed8e3a282e6..f2e7be896687c8 100644
--- a/Modules/_ssl/cert.c
+++ b/Modules/_ssl/cert.c
@@ -153,13 +153,13 @@ _x509name_print(_sslmodulestate *state, X509_NAME *name, 
int indent, unsigned lo
  * PySSLCertificate_Type
  */
 
-#define _PySSLCertificate_CAST(op)  ((PySSLCertificate *)(op))
+#define PySSLCertificate_CAST(op)   ((PySSLCertificate *)(op))
 
 static PyObject *
 certificate_repr(PyObject *op)
 {
     PyObject *osubject, *result;
-    PySSLCertificate *self = _PySSLCertificate_CAST(op);
+    PySSLCertificate *self = PySSLCertificate_CAST(op);
 
     /* subject string is ASCII encoded, UTF-8 chars are quoted */
     osubject = _x509name_print(
@@ -181,7 +181,7 @@ certificate_repr(PyObject *op)
 static Py_hash_t
 certificate_hash(PyObject *op)
 {
-    PySSLCertificate *self = _PySSLCertificate_CAST(op);
+    PySSLCertificate *self = PySSLCertificate_CAST(op);
     if (self->hash == (Py_hash_t)-1) {
         unsigned long hash;
         hash = X509_subject_name_hash(self->cert);
@@ -198,7 +198,7 @@ static PyObject *
 certificate_richcompare(PyObject *lhs, PyObject *rhs, int op)
 {
     int cmp;
-    PySSLCertificate *self = _PySSLCertificate_CAST(lhs);
+    PySSLCertificate *self = PySSLCertificate_CAST(lhs);
     _sslmodulestate *state = get_state_cert(self);
 
     if (Py_TYPE(rhs) != state->PySSLCertificate_Type) {
@@ -219,7 +219,7 @@ certificate_richcompare(PyObject *lhs, PyObject *rhs, int 
op)
 static void
 certificate_dealloc(PyObject *op)
 {
-    PySSLCertificate *self = _PySSLCertificate_CAST(op);
+    PySSLCertificate *self = PySSLCertificate_CAST(op);
     PyTypeObject *tp = Py_TYPE(self);
     X509_free(self->cert);
     (void)Py_TYPE(self)->tp_free(self);
diff --git a/Modules/_ssl/debughelpers.c b/Modules/_ssl/debughelpers.c
index 318c045a0eec3c..e4ff8b6e255adb 100644
--- a/Modules/_ssl/debughelpers.c
+++ b/Modules/_ssl/debughelpers.c
@@ -85,7 +85,9 @@ _PySSL_msg_callback(int write_p, int version, int 
content_type,
 
 
 static PyObject *
-_PySSLContext_get_msg_callback(PySSLContext *self, void *c) {
+_PySSLContext_get_msg_callback(PyObject *op, void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
     if (self->msg_cb != NULL) {
         return Py_NewRef(self->msg_cb);
     } else {
@@ -94,7 +96,10 @@ _PySSLContext_get_msg_callback(PySSLContext *self, void *c) {
 }
 
 static int
-_PySSLContext_set_msg_callback(PySSLContext *self, PyObject *arg, void *c) {
+_PySSLContext_set_msg_callback(PyObject *op, PyObject *arg,
+                               void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
     Py_CLEAR(self->msg_cb);
     if (arg == Py_None) {
         SSL_CTX_set_msg_callback(self->ctx, NULL);
@@ -153,7 +158,9 @@ _PySSL_keylog_callback(const SSL *ssl, const char *line)
 }
 
 static PyObject *
-_PySSLContext_get_keylog_filename(PySSLContext *self, void *c) {
+_PySSLContext_get_keylog_filename(PyObject *op, void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
     if (self->keylog_filename != NULL) {
         return Py_NewRef(self->keylog_filename);
     } else {
@@ -162,7 +169,10 @@ _PySSLContext_get_keylog_filename(PySSLContext *self, void 
*c) {
 }
 
 static int
-_PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) {
+_PySSLContext_set_keylog_filename(PyObject *op, PyObject *arg,
+                                  void *Py_UNUSED(closure))
+{
+    PySSLContext *self = PySSLContext_CAST(op);
     FILE *fp;
     /* Reset variables and callback first */
     SSL_CTX_set_keylog_callback(self->ctx, NULL);

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to