Skip to content

Commit

Permalink
pythongh-128657: fix _hashopenssl ref/data race
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-pytel committed Jan 15, 2025
1 parent 40a4d88 commit a3215e1
Showing 1 changed file with 17 additions and 7 deletions.
24 changes: 17 additions & 7 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "Python.h"
#include "pycore_hashtable.h"
#include "pycore_strhex.h" // _Py_strhex()
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED
#include "hashlib.h"

/* EVP is the preferred interface to hashing in OpenSSL */
Expand Down Expand Up @@ -369,6 +370,7 @@ static PY_EVP_MD*
py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
{
PY_EVP_MD *digest = NULL;
PY_EVP_MD *other_digest = NULL;
_hashlibstate *state = get_hashlib_state(module);
py_hashentry_t *entry = (py_hashentry_t *)_Py_hashtable_get(
state->hashtable, (const void*)name
Expand All @@ -379,20 +381,28 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
case Py_ht_evp:
case Py_ht_mac:
case Py_ht_pbkdf2:
if (entry->evp == NULL) {
entry->evp = PY_EVP_MD_fetch(entry->ossl_name, NULL);
digest = FT_ATOMIC_LOAD_PTR_RELAXED(entry->evp);
if (digest == NULL) {
digest = PY_EVP_MD_fetch(entry->ossl_name, NULL);
// exchange just in case another thread did same thing at same time
other_digest = _Py_atomic_exchange_ptr(&entry->evp, digest);
}
digest = entry->evp;
break;
case Py_ht_evp_nosecurity:
if (entry->evp_nosecurity == NULL) {
entry->evp_nosecurity = PY_EVP_MD_fetch(entry->ossl_name, "-fips");
digest = FT_ATOMIC_LOAD_PTR_RELAXED(entry->evp_nosecurity);
if (digest == NULL) {
digest = PY_EVP_MD_fetch(entry->ossl_name, "-fips");
// exchange just in case another thread did same thing at same time
other_digest = _Py_atomic_exchange_ptr(&entry->evp_nosecurity, digest);
}
digest = entry->evp_nosecurity;
break;
}
// if another thread same thing at same time make sure we got same ptr
assert(other_digest == NULL || other_digest == digest);
if (digest != NULL) {
PY_EVP_MD_up_ref(digest);
if (other_digest == NULL) {
PY_EVP_MD_up_ref(digest);
}
}
} else {
// Fall back for looking up an unindexed OpenSSL specific name.
Expand Down

0 comments on commit a3215e1

Please sign in to comment.