? a ? python.port.mk.yes-diff ? wheels.diff ? pkg/PLIST-main.int Index: Makefile =================================================================== RCS file: /cvs/ports/lang/python/3/Makefile,v diff -u -p -r1.34 Makefile --- Makefile 28 Sep 2026 08:39:45 -0000 1.34 +++ Makefile 30 Sep 2026 20:07:26 -0000 @@ -4,6 +4,7 @@ # Python itself. FULL_VERSION = 3.14.7 +REVISION-main = 0 SHARED_LIBS = python3.14 0.0 VERSION_SPEC = >=3.14 PORTROACH = limit:^3\.14 Index: patches/patch-Modules__ssl_c =================================================================== RCS file: patches/patch-Modules__ssl_c diff -N patches/patch-Modules__ssl_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-Modules__ssl_c 30 Sep 2026 20:07:26 -0000 @@ -0,0 +1,90 @@ +From cd7e51e7d4563866fbaa1e2521ae69b45daf3698 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 30 Sep 2026 09:16:26 -0700 +Subject: [PATCH] [3.14] gh-156293: Use-after-free for server-side SSLContext + with sni_callback (GH-158504) (#158515) + +Index: Modules/_ssl.c +--- Modules/_ssl.c.orig ++++ Modules/_ssl.c +@@ -3351,6 +3351,9 @@ context_dealloc(PyObject *op) + /* bpo-31095: UnTrack is needed before calling any callbacks */ + PyObject_GC_UnTrack(self); + (void)context_clear(op); ++ /* The SSL_CTX may outlive this object as the session_ctx of sockets that ++ were switched to another context; leave no Python callback behind. */ ++ SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); + SSL_CTX_free(self->ctx); + PyMem_FREE(self->alpn_protocols); + tp->tp_free(self); +@@ -4664,10 +4667,10 @@ _ssl__SSLContext_set_ecdh_curve_impl(PySSLContext *sel + } + + static int +-_servername_callback(SSL *s, int *al, void *args) ++_servername_callback(SSL *s, int *al, void *Py_UNUSED(args)) + { + int ret; +- PySSLContext *sslctx = (PySSLContext *) args; ++ PySSLContext *sslctx; + PySSLSocket *ssl; + PyObject *result; + /* The high-level ssl.SSLSocket object */ +@@ -4676,18 +4679,30 @@ _servername_callback(SSL *s, int *al, void *args) + const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + PyGILState_STATE gstate = PyGILState_Ensure(); + ++ /* Do not use the SSL_CTX's servername arg to find the context: it is a ++ borrowed pointer to whichever _SSLContext installed the callback, and ++ that object may already be gone while OpenSSL still reaches this ++ callback through the connection's session_ctx (e.g. on the second ++ ClientHello after a HelloRetryRequest, once sni_callback has switched ++ the socket to another context). The socket's current context is ++ always alive. */ ++ ssl = SSL_get_app_data(s); ++ assert(ssl != NULL); ++ Py_BEGIN_CRITICAL_SECTION(ssl); ++ sslctx = (PySSLContext *)Py_NewRef(ssl->ctx); ++ Py_END_CRITICAL_SECTION(); ++ assert(Py_IS_TYPE(ssl, get_state_ctx(sslctx)->PySSLSocket_Type)); ++ + Py_BEGIN_CRITICAL_SECTION(sslctx); + sni_cb = Py_XNewRef(sslctx->set_sni_cb); + Py_END_CRITICAL_SECTION(); + + if (sni_cb == NULL) { ++ Py_DECREF(sslctx); + PyGILState_Release(gstate); + return SSL_TLSEXT_ERR_OK; + } + +- ssl = SSL_get_app_data(s); +- assert(Py_IS_TYPE(ssl, get_state_ctx(sslctx)->PySSLSocket_Type)); +- + /* The servername callback expects an argument that represents the current + * SSL connection and that has a .context attribute that can be changed to + * identify the requested hostname. Since the official API is the Python +@@ -4770,12 +4785,14 @@ _servername_callback(SSL *s, int *al, void *args) + } + + Py_DECREF(sni_cb); ++ Py_DECREF(sslctx); + PyGILState_Release(gstate); + return ret; + + error: + Py_XDECREF(ssl_socket); + Py_XDECREF(sni_cb); ++ Py_DECREF(sslctx); + *al = SSL_AD_INTERNAL_ERROR; + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + PyGILState_Release(gstate); +@@ -4832,7 +4849,6 @@ _ssl__SSLContext_sni_callback_set_impl(PySSLContext *s + } + else { + Py_XSETREF(self->set_sni_cb, Py_NewRef(value)); +- SSL_CTX_set_tlsext_servername_arg(self->ctx, self); + SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); + } + return 0;