diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index fcbbec0b3..1b98a11ca 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -59,6 +59,19 @@ ossl_sslctx_mark(void *ptr) rb_gc_mark_movable((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx)); } +/* + * The SSLContext's VALUE is stored in exactly one place -- the SSL_CTX's ex_data, + * which ossl_sslctx_compact keeps up to date. Callbacks must go through here rather + * than capture their own copy, which nothing would relocate. + */ +static VALUE +ossl_sslctx_obj_from_ssl(const SSL *ssl) +{ + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + return (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx); +} + static void ossl_sslctx_free(void *ptr) { @@ -584,7 +597,8 @@ static int ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) { - VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded); + VALUE protocols = rb_attr_get(ossl_sslctx_obj_from_ssl(ssl), + id_npn_protocols_encoded); *out = (const unsigned char *) RSTRING_PTR(protocols); *outlen = RSTRING_LENINT(protocols); @@ -598,7 +612,7 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, { VALUE sslctx_obj, cb; - sslctx_obj = (VALUE) arg; + sslctx_obj = ossl_sslctx_obj_from_ssl(ssl); cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb); return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out, @@ -612,7 +626,7 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, { VALUE sslctx_obj, cb; - sslctx_obj = (VALUE) arg; + sslctx_obj = ossl_sslctx_obj_from_ssl(ssl); cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb); return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen); @@ -807,11 +821,11 @@ ossl_sslctx_setup(VALUE self) if (!NIL_P(val)) { VALUE encoded = ssl_encode_npn_protocols(val); rb_ivar_set(self, id_npn_protocols_encoded, encoded); - SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self); + SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, NULL); OSSL_Debug("SSL NPN advertise callback added"); } if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) { - SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self); + SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, NULL); OSSL_Debug("SSL NPN select callback added"); } #endif @@ -827,7 +841,7 @@ ossl_sslctx_setup(VALUE self) OSSL_Debug("SSL ALPN values added"); } if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) { - SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self); + SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, NULL); OSSL_Debug("SSL ALPN select callback added"); }