Commit 7933e2ca6e for openssl.org

commit 7933e2ca6ead9a2fb16aa3fde783e66386570592
Author: Neil Horman <nhorman@openssl.org>
Date:   Fri May 8 10:46:54 2026 -0400

    make OSSL_DECODER no do ref counting

    Reviewed-by: Bob Beck <beck@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    MergeDate: Thu Jun 25 21:26:11 2026
    (Merged from https://github.com/openssl/openssl/pull/31143)

diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
index b38f1adf5b..315c99d8c6 100644
--- a/crypto/encode_decode/decoder_meth.c
+++ b/crypto/encode_decode/decoder_meth.c
@@ -59,7 +59,7 @@ static OSSL_DECODER *ossl_decoder_new(void)
     if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL)
         return NULL;
     if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) {
-        OSSL_DECODER_free(decoder);
+        ossl_decoder_free(decoder);
         return NULL;
     }

@@ -68,9 +68,17 @@ static OSSL_DECODER *ossl_decoder_new(void)

 int OSSL_DECODER_up_ref(OSSL_DECODER *decoder)
 {
-#ifdef OSSL_DECODER_fetch
+#ifdef OPENSSL_NO_CACHED_FETCH
     return ossl_decoder_up_ref(decoder);
 #else
+    /*
+     * DECODERS do something weird.  They manually build methods rather than
+     * attempt to fetch them from the method store or construct them through
+     * the ossl_generic_fetch mechanism.  As such they don't make use of the refcounting
+     * that we rely on in the method store, and so we always need to refcount them here
+     * We can identify them based on the fact that they never have a registered nid (i.e.
+     * its always zero)
+     */
     if (decoder->base.id == 0)
         return ossl_decoder_up_ref(decoder);
     return 1;
@@ -79,7 +87,7 @@ int OSSL_DECODER_up_ref(OSSL_DECODER *decoder)

 void OSSL_DECODER_free(OSSL_DECODER *decoder)
 {
-#ifdef OSSL_DECODER_fetch
+#ifdef OPENSSL_NO_CACHED_FETCH
     ossl_decoder_free(decoder);
 #else
     if (decoder != NULL && decoder->base.id == 0)
@@ -230,14 +238,14 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
         return NULL;
     decoder->base.id = id;
     if ((decoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
-        OSSL_DECODER_free(decoder);
+        ossl_decoder_free(decoder);
         return NULL;
     }
     decoder->base.algodef = algodef;
     if ((decoder->base.parsed_propdef
             = ossl_parse_property(libctx, algodef->property_definition))
         == NULL) {
-        OSSL_DECODER_free(decoder);
+        ossl_decoder_free(decoder);
         return NULL;
     }

@@ -289,13 +297,13 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
     if (!((decoder->newctx == NULL && decoder->freectx == NULL)
             || (decoder->newctx != NULL && decoder->freectx != NULL))
         || decoder->decode == NULL) {
-        OSSL_DECODER_free(decoder);
+        ossl_decoder_free(decoder);
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
     }

     if (prov != NULL && !ossl_provider_up_ref(prov)) {
-        OSSL_DECODER_free(decoder);
+        ossl_decoder_free(decoder);
         return NULL;
     }

@@ -341,17 +349,7 @@ static void *construct_decoder(const OSSL_ALGORITHM *algodef,
 /* Intermediary function to avoid ugly casts, used below */
 static void destruct_decoder(void *method, void *data)
 {
-    OSSL_DECODER_free(method);
-}
-
-static int up_ref_decoder(void *method)
-{
-    return OSSL_DECODER_up_ref(method);
-}
-
-static void free_decoder(void *method)
-{
-    OSSL_DECODER_free(method);
+    ossl_decoder_free(method);
 }

 /* Fetching support.  Can fetch by numeric identity or by name */
@@ -409,7 +407,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata,
                 id = ossl_namemap_name2num(namemap, name);
             if (id != 0)
                 ossl_method_store_cache_set(store, prov, id, propq, method,
-                    up_ref_decoder, free_decoder);
+                    ossl_decoder_up_ref, ossl_decoder_free);
         }

         /*
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
index 0c9647e51f..611dc787d7 100644
--- a/crypto/encode_decode/encoder_meth.c
+++ b/crypto/encode_decode/encoder_meth.c
@@ -27,12 +27,29 @@

 static void ossl_encoder_free(void *data)
 {
-    OSSL_ENCODER_free(data);
+    OSSL_ENCODER *encoder = (OSSL_ENCODER *)data;
+    int ref = 0;
+
+    if (encoder == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref);
+    if (ref > 0)
+        return;
+    OPENSSL_free(encoder->base.name);
+    ossl_property_free(encoder->base.parsed_propdef);
+    ossl_provider_free(encoder->base.prov);
+    CRYPTO_FREE_REF(&encoder->base.refcnt);
+    OPENSSL_free(encoder);
 }

 static int ossl_encoder_up_ref(void *data)
 {
-    return OSSL_ENCODER_up_ref(data);
+    OSSL_ENCODER *encoder = (OSSL_ENCODER *)data;
+    int ref = 0;
+
+    CRYPTO_UP_REF(&encoder->base.refcnt, &ref);
+    return 1;
 }

 /* Simple method structure constructor and destructor */
@@ -56,6 +73,7 @@ int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder)
     return ossl_encoder_up_ref(encoder);
 #else
     return 1;
+#endif
 }

 void OSSL_ENCODER_free(OSSL_ENCODER *encoder)
@@ -208,14 +226,14 @@ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
         return NULL;
     encoder->base.id = id;
     if ((encoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
-        OSSL_ENCODER_free(encoder);
+        ossl_encoder_free(encoder);
         return NULL;
     }
     encoder->base.algodef = algodef;
     if ((encoder->base.parsed_propdef
             = ossl_parse_property(libctx, algodef->property_definition))
         == NULL) {
-        OSSL_ENCODER_free(encoder);
+        ossl_encoder_free(encoder);
         return NULL;
     }

@@ -273,13 +291,13 @@ static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
             || (encoder->import_object != NULL && encoder->free_object != NULL)
             || (encoder->import_object == NULL && encoder->free_object == NULL))
         || encoder->encode == NULL) {
-        OSSL_ENCODER_free(encoder);
+        ossl_encoder_free(encoder);
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
     }

     if (prov != NULL && !ossl_provider_up_ref(prov)) {
-        OSSL_ENCODER_free(encoder);
+        ossl_encoder_free(encoder);
         return NULL;
     }

@@ -325,17 +343,7 @@ static void *construct_encoder(const OSSL_ALGORITHM *algodef,
 /* Intermediary function to avoid ugly casts, used below */
 static void destruct_encoder(void *method, void *data)
 {
-    OSSL_ENCODER_free(method);
-}
-
-static int up_ref_encoder(void *method)
-{
-    return OSSL_ENCODER_up_ref(method);
-}
-
-static void free_encoder(void *method)
-{
-    OSSL_ENCODER_free(method);
+    ossl_encoder_free(method);
 }

 /* Fetching support.  Can fetch by numeric identity or by name */
@@ -392,7 +400,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata,
             if (id == 0)
                 id = ossl_namemap_name2num(namemap, name);
             ossl_method_store_cache_set(store, prov, id, propq, method,
-                up_ref_encoder, free_encoder);
+                ossl_encoder_up_ref, ossl_encoder_free);
         }

         /*