27
27
#include "pycore_hashtable.h"
28
28
#include "pycore_pyhash.h" // _Py_HashBytes()
29
29
#include "pycore_strhex.h" // _Py_strhex()
30
+ #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED
30
31
#include "hashlib.h"
31
32
32
33
/* EVP is the preferred interface to hashing in OpenSSL */
33
34
#include <openssl/evp.h>
34
35
#include <openssl/hmac.h>
35
- #include <openssl/crypto.h> // FIPS_mode()
36
+ #include <openssl/crypto.h> // FIPS_mode()
36
37
/* We use the object interface to discover what hashes OpenSSL supports. */
37
38
#include <openssl/objects.h>
38
39
#include <openssl/err.h>
@@ -370,6 +371,7 @@ static PY_EVP_MD*
370
371
py_digest_by_name (PyObject * module , const char * name , enum Py_hash_type py_ht )
371
372
{
372
373
PY_EVP_MD * digest = NULL ;
374
+ PY_EVP_MD * other_digest = NULL ;
373
375
_hashlibstate * state = get_hashlib_state (module );
374
376
py_hashentry_t * entry = (py_hashentry_t * )_Py_hashtable_get (
375
377
state -> hashtable , (const void * )name
@@ -380,20 +382,36 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
380
382
case Py_ht_evp :
381
383
case Py_ht_mac :
382
384
case Py_ht_pbkdf2 :
383
- if (entry -> evp == NULL ) {
384
- entry -> evp = PY_EVP_MD_fetch (entry -> ossl_name , NULL );
385
+ digest = FT_ATOMIC_LOAD_PTR_RELAXED (entry -> evp );
386
+ if (digest == NULL ) {
387
+ digest = PY_EVP_MD_fetch (entry -> ossl_name , NULL );
388
+ #ifdef Py_GIL_DISABLED
389
+ // exchange just in case another thread did same thing at same time
390
+ other_digest = _Py_atomic_exchange_ptr (& entry -> evp , digest );
391
+ #else
392
+ entry -> evp = digest ;
393
+ #endif
385
394
}
386
- digest = entry -> evp ;
387
395
break ;
388
396
case Py_ht_evp_nosecurity :
389
- if (entry -> evp_nosecurity == NULL ) {
390
- entry -> evp_nosecurity = PY_EVP_MD_fetch (entry -> ossl_name , "-fips" );
397
+ digest = FT_ATOMIC_LOAD_PTR_RELAXED (entry -> evp_nosecurity );
398
+ if (digest == NULL ) {
399
+ digest = PY_EVP_MD_fetch (entry -> ossl_name , "-fips" );
400
+ #ifdef Py_GIL_DISABLED
401
+ // exchange just in case another thread did same thing at same time
402
+ other_digest = _Py_atomic_exchange_ptr (& entry -> evp_nosecurity , digest );
403
+ #else
404
+ entry -> evp_nosecurity = digest ;
405
+ #endif
391
406
}
392
- digest = entry -> evp_nosecurity ;
393
407
break ;
394
408
}
409
+ // if another thread same thing at same time make sure we got same ptr
410
+ assert (other_digest == NULL || other_digest == digest );
395
411
if (digest != NULL ) {
396
- PY_EVP_MD_up_ref (digest );
412
+ if (other_digest == NULL ) {
413
+ PY_EVP_MD_up_ref (digest );
414
+ }
397
415
}
398
416
} else {
399
417
// Fall back for looking up an unindexed OpenSSL specific name.
0 commit comments