Commit bed6d88c26 for openssl.org

commit bed6d88c267e43ef6d4c1f5f1fd144cd42fcd208
Author: Alexandr Nedvedicky <sashan@openssl.org>
Date:   Thu Apr 23 15:57:26 2026 +0200

    remove ossl_quic_detach_stream() and ossl_quic_attach_stream()

    Those function used to be backends for SSL_attach_stream() and
    SSL_detach_stream(). Both those functions were removed from
    API back 2023. And it does not look like there is a plan
    to revive them. This PR removes implementation of stream detach/attach
    functions with their tests.

    Reviewed-by: Matt Caswell <matt@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    MergeDate: Sun Apr 26 13:26:58 2026
    (Merged from https://github.com/openssl/openssl/pull/30956)

diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h
index 88168d169c..45b8e090ed 100644
--- a/include/internal/quic_ssl.h
+++ b/include/internal/quic_ssl.h
@@ -107,8 +107,6 @@ __owur int ossl_quic_get_stream_type(SSL *s);
 __owur uint64_t ossl_quic_get_stream_id(SSL *s);
 __owur int ossl_quic_is_stream_local(SSL *s);
 __owur int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode);
-__owur SSL *ossl_quic_detach_stream(SSL *s);
-__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
 __owur int ossl_quic_set_incoming_stream_policy(SSL *s, int policy,
     uint64_t aec);
 __owur SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags);
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 9dfd28c930..3d49857458 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -3484,83 +3484,6 @@ int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
     return 1;
 }

-/*
- * SSL_detach_stream
- * -----------------
- */
-QUIC_TAKES_LOCK
-SSL *ossl_quic_detach_stream(SSL *s)
-{
-    QCTX ctx;
-    QUIC_XSO *xso = NULL;
-
-    if (!expect_quic_conn_only(s, &ctx))
-        return NULL;
-
-    qctx_lock(&ctx);
-
-    /* Calling this function inhibits default XSO autocreation. */
-    /* QC ref to any default XSO is transferred to us and to caller. */
-    qc_set_default_xso_keep_ref(ctx.qc, NULL, /*touch=*/1, &xso);
-
-    qctx_unlock(&ctx);
-
-    return xso != NULL ? &xso->obj.ssl : NULL;
-}
-
-/*
- * SSL_attach_stream
- * -----------------
- */
-QUIC_TAKES_LOCK
-int ossl_quic_attach_stream(SSL *conn, SSL *stream)
-{
-    QCTX ctx;
-    QUIC_XSO *xso;
-    int nref;
-
-    if (!expect_quic_conn_only(conn, &ctx))
-        return 0;
-
-    if (stream == NULL || stream->type != SSL_TYPE_QUIC_XSO)
-        return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_NULL_PARAMETER,
-            "stream to attach must be a valid QUIC stream");
-
-    xso = (QUIC_XSO *)stream;
-
-    qctx_lock(&ctx);
-
-    if (ctx.qc->default_xso != NULL) {
-        qctx_unlock(&ctx);
-        return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
-            "connection already has a default stream");
-    }
-
-    /*
-     * It is a caller error for the XSO being attached as a default XSO to have
-     * more than one ref.
-     */
-    if (!CRYPTO_GET_REF(&xso->obj.ssl.references, &nref)) {
-        qctx_unlock(&ctx);
-        return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_INTERNAL_ERROR,
-            "ref");
-    }
-
-    if (nref != 1) {
-        qctx_unlock(&ctx);
-        return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
-            "stream being attached must have "
-            "only 1 reference");
-    }
-
-    /* Caller's reference to the XSO is transferred to us. */
-    /* Calling this function inhibits default XSO autocreation. */
-    qc_set_default_xso(ctx.qc, xso, /*touch=*/1);
-
-    qctx_unlock(&ctx);
-    return 1;
-}
-
 /*
  * SSL_set_incoming_stream_policy
  * ------------------------------
diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c
index e59cd0be87..3bb1bd9a0b 100644
--- a/test/quic_multistream_test.c
+++ b/test/quic_multistream_test.c
@@ -155,8 +155,6 @@ struct script_op {
 #define OPK_S_EXPECT_FIN 9
 #define OPK_C_CONCLUDE 10
 #define OPK_S_CONCLUDE 11
-#define OPK_C_DETACH 12
-#define OPK_C_ATTACH 13
 #define OPK_C_NEW_STREAM 14
 #define OPK_S_NEW_STREAM 15
 #define OPK_C_ACCEPT_STREAM_WAIT 16
@@ -243,10 +241,6 @@ struct script_op {
     { OPK_C_CONCLUDE, NULL, 0, NULL, #stream_name }
 #define OP_S_CONCLUDE(stream_name) \
     { OPK_S_CONCLUDE, NULL, 0, NULL, #stream_name }
-#define OP_C_DETACH(stream_name) \
-    { OPK_C_DETACH, NULL, 0, NULL, #stream_name }
-#define OP_C_ATTACH(stream_name) \
-    { OPK_C_ATTACH, NULL, 0, NULL, #stream_name }
 #define OP_C_NEW_STREAM_BIDI(stream_name, expect_id) \
     { OPK_C_NEW_STREAM, NULL, 0, NULL, #stream_name, (expect_id) }
 #define OP_C_NEW_STREAM_BIDI_EX(stream_name, expect_id, flags) \
@@ -1449,36 +1443,6 @@ static int run_script_worker(struct helper *h, const struct script_op *script,
                 S_SPIN_AGAIN();
         } break;

-        case OPK_C_DETACH: {
-            SSL *c_stream;
-
-            if (!TEST_ptr_null(c_tgt))
-                goto out; /* don't overwrite existing stream with same name */
-
-            if (!TEST_ptr(op->stream_name))
-                goto out;
-
-            if (!TEST_ptr(c_stream = ossl_quic_detach_stream(h->c_conn)))
-                goto out;
-
-            if (!TEST_true(helper_local_set_c_stream(hl, op->stream_name, c_stream)))
-                goto out;
-        } break;
-
-        case OPK_C_ATTACH: {
-            if (!TEST_ptr(c_tgt))
-                goto out;
-
-            if (!TEST_ptr(op->stream_name))
-                goto out;
-
-            if (!TEST_true(ossl_quic_attach_stream(h->c_conn, c_tgt)))
-                goto out;
-
-            if (!TEST_true(helper_local_set_c_stream(hl, op->stream_name, NULL)))
-                goto out;
-        } break;
-
         case OPK_C_NEW_STREAM: {
             SSL *c_stream;
             uint64_t flags = op->arg1;
@@ -2181,52 +2145,22 @@ static const struct script_op script_2[] = {

 /* 3. Default stream detach/reattach test */
 static const struct script_op script_3[] = {
-    OP_C_SET_ALPN("ossltest"),
-    OP_C_CONNECT_WAIT(),
-
-    OP_C_WRITE(DEFAULT, "apple", 5),
-    OP_C_DETACH(a), /* DEFAULT becomes stream 'a' */
-    OP_C_WRITE_FAIL(DEFAULT),
-
-    OP_C_WRITE(a, "by", 2),
-
-    OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)),
-    OP_S_READ_EXPECT(a, "appleby", 7),
-
-    OP_S_WRITE(a, "hello", 5),
-    OP_C_READ_EXPECT(a, "hello", 5),
-
-    OP_C_WRITE_FAIL(DEFAULT),
-    OP_C_ATTACH(a),
-    OP_C_WRITE(DEFAULT, "is here", 7),
-    OP_S_READ_EXPECT(a, "is here", 7),
-
-    OP_C_DETACH(a),
-    OP_C_CONCLUDE(a),
-    OP_S_EXPECT_FIN(a),
+    /*
+     * SSL_attach_stream()/SSL_detach_stream() no longer exists,
+     * there is no reason to keep their private implementation
+     * with test
+     */

     OP_END
 };

 /* 4. Default stream mode test */
 static const struct script_op script_4[] = {
-    OP_C_SET_ALPN("ossltest"),
-    OP_C_CONNECT_WAIT(),
-
-    OP_C_SET_DEFAULT_STREAM_MODE(SSL_DEFAULT_STREAM_MODE_NONE),
-    OP_C_WRITE_FAIL(DEFAULT),
-
-    OP_S_NEW_STREAM_BIDI(a, S_BIDI_ID(0)),
-    OP_S_WRITE(a, "apple", 5),
-
-    OP_C_READ_FAIL(DEFAULT),
-
-    OP_C_ACCEPT_STREAM_WAIT(a),
-    OP_C_READ_EXPECT(a, "apple", 5),
-
-    OP_C_ATTACH(a),
-    OP_C_WRITE(DEFAULT, "orange", 6),
-    OP_S_READ_EXPECT(a, "orange", 6),
+    /*
+     * SSL_attach_stream()/SSL_detach_stream() no longer exists,
+     * there is no reason to keep their private implementation
+     * with test
+     */

     OP_END
 };
diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c
index c64f37ddda..d9f374f8e1 100644
--- a/test/radix/quic_ops.c
+++ b/test/radix/quic_ops.c
@@ -747,54 +747,6 @@ err:
     return ok;
 }

-DEF_FUNC(hf_detach)
-{
-    int ok = 0;
-    const char *conn_name, *stream_name;
-    SSL *conn, *stream;
-
-    F_POP2(conn_name, stream_name);
-    if (!TEST_ptr(conn = RADIX_PROCESS_get_ssl(RP(), conn_name)))
-        goto err;
-
-    if (!TEST_ptr(stream = ossl_quic_detach_stream(conn)))
-        goto err;
-
-    if (!TEST_true(RADIX_PROCESS_set_ssl(RP(), stream_name, stream))) {
-        SSL_free(stream);
-        goto err;
-    }
-
-    ok = 1;
-err:
-    return ok;
-}
-
-DEF_FUNC(hf_attach)
-{
-    int ok = 0;
-    const char *conn_name, *stream_name;
-    SSL *conn, *stream;
-
-    F_POP2(conn_name, stream_name);
-
-    if (!TEST_ptr(conn = RADIX_PROCESS_get_ssl(RP(), conn_name)))
-        goto err;
-
-    if (!TEST_ptr(stream = RADIX_PROCESS_get_ssl(RP(), stream_name)))
-        goto err;
-
-    if (!TEST_true(ossl_quic_attach_stream(conn, stream)))
-        goto err;
-
-    if (!TEST_true(RADIX_PROCESS_set_ssl(RP(), stream_name, NULL)))
-        goto err;
-
-    ok = 1;
-err:
-    return ok;
-}
-
 DEF_FUNC(hf_expect_fin)
 {
     int ok = 0, ret;
@@ -1215,16 +1167,6 @@ err:
         OP_PUSH_PZ(reason),                               \
         OP_FUNC(hf_shutdown_wait))

-#define OP_DETACH(conn_name, stream_name) \
-    (OP_SELECT_SSL(0, conn_name),         \
-        OP_PUSH_PZ(#stream_name),         \
-        OP_FUNC(hf_detach))
-
-#define OP_ATTACH(conn_name, stream_name) \
-    (OP_SELECT_SSL(0, conn_name),         \
-        OP_PUSH_PZ(stream_name),          \
-        OP_FUNC(hf_attach))
-
 #define OP_EXPECT_FIN(name)  \
     (OP_SELECT_SSL(0, name), \
         OP_FUNC(hf_expect_fin))