Commit f454c8fd5d for openssl.org
commit f454c8fd5d97b80f431dba16b8deacad6b69cbfd
Author: Neil Horman <nhorman@openssl.org>
Date: Fri Jul 3 08:40:06 2026 -0400
Fix refcounting for ENCODER/DECODER/STORE methods without caching
https://github.com/openssl/openssl/pull/31782
Fixed method refcounting for EVP objects when the provider they are
fetched from requests no-caching, but I neglected to add simmilar
refcounting fixes for DECODERS/ENCODERS and STORE objects, who follow a
different fetch path (these use inner_[decoder|encoder|loader]_fetch
rather than inner_evp_generic_fetch.
They got missed because the p_ossltest provider that we use to test
these paths don't provide these objects, so the path never got
exercised.
Reviewed-by: Bob Beck <beck@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
MergeDate: Tue Jul 14 05:21:36 2026
(Merged from https://github.com/openssl/openssl/pull/31844)
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
index 995cb675ba..772c29c031 100644
--- a/crypto/encode_decode/decoder_meth.c
+++ b/crypto/encode_decode/decoder_meth.c
@@ -406,9 +406,19 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata,
*/
if (id == 0 && name != NULL)
id = ossl_namemap_name2num(namemap, name);
- if (id != 0)
+ if (id != 0 && methdata->tmp_store == NULL) {
ossl_method_store_cache_set(store, prov, id, propq, method,
ossl_decoder_up_ref, ossl_decoder_free);
+ } else {
+ /*
+ * Like with EVP methods, if the provider requests no caching we need
+ * to take an extra refcount here so that the tmp_stored decoder
+ * lives beyond the freeing of that tmp_store
+ */
+#ifndef OPENSSL_NO_CACHED_FETCH
+ OSSL_DECODER_up_ref((OSSL_DECODER *)method);
+#endif
+ }
}
/*
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
index f329d0a307..23dcccebb9 100644
--- a/crypto/encode_decode/encoder_meth.c
+++ b/crypto/encode_decode/encoder_meth.c
@@ -405,8 +405,19 @@ 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,
- ossl_encoder_up_ref, ossl_encoder_free);
+ if (id != 0 && methdata->tmp_store == NULL) {
+ ossl_method_store_cache_set(store, prov, id, propq, method,
+ ossl_encoder_up_ref, ossl_encoder_free);
+ } else {
+ /*
+ * Like with EVP methods, if the provider requests no caching we need
+ * to take an extra refcount here so that the tmp_stored encoder
+ * lives beyond the freeing of that tmp_store
+ */
+#ifndef OPENSSL_NO_CACHED_FETCH
+ OSSL_ENCODER_up_ref((OSSL_ENCODER *)method);
+#endif
+ }
}
/*
diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c
index 96b092e5bb..976e4aa734 100644
--- a/crypto/store/store_meth.c
+++ b/crypto/store/store_meth.c
@@ -353,8 +353,19 @@ inner_loader_fetch(struct loader_data_st *methdata,
*/
if (id == 0)
id = ossl_namemap_name2num(namemap, scheme);
- ossl_method_store_cache_set(store, prov, id, propq, method,
- up_ref_loader, free_loader);
+ if (id != 0 && methdata->tmp_store == NULL) {
+ ossl_method_store_cache_set(store, prov, id, propq, method,
+ up_ref_loader, free_loader);
+ } else {
+ /*
+ * Like with EVP methods, if the provider requests no caching we need
+ * to take an extra refcount here so that the tmp_stored loader
+ * lives beyond the freeing of that tmp_store
+ */
+#ifndef OPENSSL_NO_CACHED_FETCH
+ OSSL_STORE_LOADER_up_ref((OSSL_STORE_LOADER *)method);
+#endif
+ }
}
/*