mirror of
https://github.com/python/cpython.git
synced 2026-03-06 13:00:50 +00:00
[3.13] gh-128657: fix _hashopenssl ref/data race (GH-128886) (GH-129853)
(cherry picked from commit 6c67904e79)
This commit is contained in:
parent
8a7146c5eb
commit
4a1389ced4
2 changed files with 29 additions and 10 deletions
|
|
@ -0,0 +1 @@
|
|||
Fix possible extra reference when using objects returned by :func:`hashlib.sha256` under :term:`free threading`.
|
||||
|
|
@ -25,14 +25,15 @@
|
|||
#include <stdbool.h>
|
||||
#include "Python.h"
|
||||
#include "pycore_hashtable.h"
|
||||
#include "pycore_pyhash.h" // _Py_HashBytes()
|
||||
#include "pycore_strhex.h" // _Py_strhex()
|
||||
#include "pycore_pyhash.h" // _Py_HashBytes()
|
||||
#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 */
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/crypto.h> // FIPS_mode()
|
||||
#include <openssl/crypto.h> // FIPS_mode()
|
||||
/* We use the object interface to discover what hashes OpenSSL supports. */
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/err.h>
|
||||
|
|
@ -370,6 +371,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
|
||||
|
|
@ -380,20 +382,36 @@ 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);
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// exchange just in case another thread did same thing at same time
|
||||
other_digest = _Py_atomic_exchange_ptr(&entry->evp, digest);
|
||||
#else
|
||||
entry->evp = digest;
|
||||
#endif
|
||||
}
|
||||
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");
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// exchange just in case another thread did same thing at same time
|
||||
other_digest = _Py_atomic_exchange_ptr(&entry->evp_nosecurity, digest);
|
||||
#else
|
||||
entry->evp_nosecurity = digest;
|
||||
#endif
|
||||
}
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue