2626#include "Python.h"
2727#include "pycore_hashtable.h"
2828#include "pycore_strhex.h" // _Py_strhex()
29+ #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED
2930#include "hashlib.h"
3031
3132/* EVP is the preferred interface to hashing in OpenSSL */
@@ -369,6 +370,7 @@ static PY_EVP_MD*
369370py_digest_by_name (PyObject * module , const char * name , enum Py_hash_type py_ht )
370371{
371372 PY_EVP_MD * digest = NULL ;
373+ PY_EVP_MD * other_digest = NULL ;
372374 _hashlibstate * state = get_hashlib_state (module );
373375 py_hashentry_t * entry = (py_hashentry_t * )_Py_hashtable_get (
374376 state -> hashtable , (const void * )name
@@ -379,20 +381,28 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
379381 case Py_ht_evp :
380382 case Py_ht_mac :
381383 case Py_ht_pbkdf2 :
382- if (entry -> evp == NULL ) {
383- entry -> evp = PY_EVP_MD_fetch (entry -> ossl_name , NULL );
384+ digest = FT_ATOMIC_LOAD_PTR_RELAXED (entry -> evp );
385+ if (digest == NULL ) {
386+ digest = PY_EVP_MD_fetch (entry -> ossl_name , NULL );
387+ // exchange just in case another thread did same thing at same time
388+ other_digest = _Py_atomic_exchange_ptr (& entry -> evp , digest );
384389 }
385- digest = entry -> evp ;
386390 break ;
387391 case Py_ht_evp_nosecurity :
388- if (entry -> evp_nosecurity == NULL ) {
389- entry -> evp_nosecurity = PY_EVP_MD_fetch (entry -> ossl_name , "-fips" );
392+ digest = FT_ATOMIC_LOAD_PTR_RELAXED (entry -> evp_nosecurity );
393+ if (digest == NULL ) {
394+ digest = PY_EVP_MD_fetch (entry -> ossl_name , "-fips" );
395+ // exchange just in case another thread did same thing at same time
396+ other_digest = _Py_atomic_exchange_ptr (& entry -> evp_nosecurity , digest );
390397 }
391- digest = entry -> evp_nosecurity ;
392398 break ;
393399 }
400+ // if another thread same thing at same time make sure we got same ptr
401+ assert (other_digest == NULL || other_digest == digest );
394402 if (digest != NULL ) {
395- PY_EVP_MD_up_ref (digest );
403+ if (other_digest == NULL ) {
404+ PY_EVP_MD_up_ref (digest );
405+ }
396406 }
397407 } else {
398408 // Fall back for looking up an unindexed OpenSSL specific name.
0 commit comments