Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-99108: Release the GIL around hashlib built-in computation #104675

Merged
merged 7 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,16 @@ get_hashlib_state(PyObject *module)
typedef struct {
PyObject_HEAD
EVP_MD_CTX *ctx; /* OpenSSL message digest context */
// Prevents undefined behavior via multiple threads entering the C API.
gpshead marked this conversation as resolved.
Show resolved Hide resolved
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock; /* OpenSSL context lock */
} EVPobject;

typedef struct {
PyObject_HEAD
HMAC_CTX *ctx; /* OpenSSL hmac context */
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock; /* HMAC context lock */
} HMACobject;

Expand Down Expand Up @@ -896,6 +900,8 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj,

if (view.buf && view.len) {
if (view.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
result = EVP_hash(self, view.buf, view.len);
Py_END_ALLOW_THREADS
Expand Down
4 changes: 4 additions & 0 deletions Modules/md5module.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ typedef long long MD5_INT64; /* 64-bit integer */

typedef struct {
PyObject_HEAD
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock;
Hacl_Streaming_MD5_state *hash_state;
} MD5object;
Expand Down Expand Up @@ -301,6 +303,8 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
gpshead marked this conversation as resolved.
Show resolved Hide resolved
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update(new->hash_state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down
4 changes: 4 additions & 0 deletions Modules/sha1module.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ typedef long long SHA1_INT64; /* 64-bit integer */

typedef struct {
PyObject_HEAD
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock;
Hacl_Streaming_SHA1_state *hash_state;
} SHA1object;
Expand Down Expand Up @@ -301,6 +303,8 @@ _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update(new->hash_state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down
12 changes: 12 additions & 0 deletions Modules/sha2module.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ class SHA512Type "SHA512object *" "&PyType_Type"
typedef struct {
PyObject_HEAD
int digestsize;
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock;
Hacl_Streaming_SHA2_state_sha2_256 *state;
} SHA256object;

typedef struct {
PyObject_HEAD
int digestsize;
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock;
Hacl_Streaming_SHA2_state_sha2_512 *state;
} SHA512object;
Expand Down Expand Up @@ -607,6 +611,8 @@ _sha2_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update_256(new->state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down Expand Up @@ -659,6 +665,8 @@ _sha2_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update_256(new->state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down Expand Up @@ -710,6 +718,8 @@ _sha2_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update_512(new->state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down Expand Up @@ -761,6 +771,8 @@ _sha2_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity)
}
if (string) {
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
update_512(new->state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down
4 changes: 4 additions & 0 deletions Modules/sha3module.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class _sha3.shake_256 "SHA3object *" "&SHAKE256type"

typedef struct {
PyObject_HEAD
// Prevents undefined behavior via multiple threads entering the C API.
// The lock will be NULL before threaded access has been enabled.
PyThread_type_lock lock;
Hacl_Streaming_Keccak_state *hash_state;
} SHA3object;
Expand Down Expand Up @@ -136,6 +138,8 @@ py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity)
if (data) {
GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
if (buf.len >= HASHLIB_GIL_MINSIZE) {
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
sha3_update(self->hash_state, buf.buf, buf.len);
Py_END_ALLOW_THREADS
Expand Down