From 4e214fa6be8eb7a1f547bfb2eb1c546162151d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:23:19 +0200 Subject: [PATCH 01/10] explode `hashlib.h` into multiple files --- Modules/_hashlib/hashlib_buffer.c | 40 ++++++ Modules/_hashlib/hashlib_buffer.h | 60 +++++++++ Modules/_hashlib/hashlib_fetch.h | 127 ++++++++++++++++++ .../{hashlib.h => _hashlib/hashlib_mutex.h} | 90 ++----------- 4 files changed, 235 insertions(+), 82 deletions(-) create mode 100644 Modules/_hashlib/hashlib_buffer.c create mode 100644 Modules/_hashlib/hashlib_buffer.h create mode 100644 Modules/_hashlib/hashlib_fetch.h rename Modules/{hashlib.h => _hashlib/hashlib_mutex.h} (53%) diff --git a/Modules/_hashlib/hashlib_buffer.c b/Modules/_hashlib/hashlib_buffer.c new file mode 100644 index 00000000000000..34811c6266fd64 --- /dev/null +++ b/Modules/_hashlib/hashlib_buffer.c @@ -0,0 +1,40 @@ +#include "hashlib_buffer.h" + +int +_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string) +{ + if (data != NULL && string == NULL) { + // called as H(data) or H(data=...) + *res = data; + return 1; + } + else if (data == NULL && string != NULL) { + // called as H(string=...) + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "the 'string' keyword parameter is deprecated since " + "Python 3.15 and slated for removal in Python 3.19; " + "use the 'data' keyword parameter or pass the data " + "to hash as a positional argument instead", 1) < 0) + { + *res = NULL; + return -1; + } + *res = string; + return 1; + } + else if (data == NULL && string == NULL) { + // fast path when no data is given + assert(!PyErr_Occurred()); + *res = NULL; + return 0; + } + else { + // called as H(data=..., string) + *res = NULL; + PyErr_SetString(PyExc_TypeError, + "'data' and 'string' are mutually exclusive " + "and support for 'string' keyword parameter " + "is slated for removal in a future version."); + return -1; + } +} diff --git a/Modules/_hashlib/hashlib_buffer.h b/Modules/_hashlib/hashlib_buffer.h new file mode 100644 index 00000000000000..13b0aa1ab3cb61 --- /dev/null +++ b/Modules/_hashlib/hashlib_buffer.h @@ -0,0 +1,60 @@ +#ifndef _HASHLIB_HASHLIB_BUFFER_H +#define _HASHLIB_HASHLIB_BUFFER_H + +#include "Python.h" + +/* + * Given an buffer-like OBJ, fill in the buffer VIEW with the result + * of PyObject_GetBuffer. + * + * On error, set an exception and execute the ERRACTION statements, + * e.g. 'return NULL' or 'goto error'. + * + * Parameters + * + * OBJ An object supporting the buffer API. + * VIEW A Py_buffer pointer to fill. + * ERRACTION The statements to execute on error. + */ +#define GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, ERRACTION) \ + do { \ + if (PyUnicode_Check((OBJ))) { \ + PyErr_SetString(PyExc_TypeError, \ + "strings must be encoded before hashing"); \ + ERRACTION; \ + } \ + if (!PyObject_CheckBuffer((OBJ))) { \ + PyErr_SetString(PyExc_TypeError, \ + "object supporting the buffer API required"); \ + ERRACTION; \ + } \ + if (PyObject_GetBuffer((OBJ), (VIEW), PyBUF_SIMPLE) == -1) { \ + ERRACTION; \ + } \ + if ((VIEW)->ndim > 1) { \ + PyErr_SetString(PyExc_BufferError, \ + "buffer must be one-dimensional"); \ + PyBuffer_Release((VIEW)); \ + ERRACTION; \ + } \ + } while(0) + +/* Specialization of GET_BUFFER_VIEW_OR_ERROR() returning NULL on error. */ +#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \ + GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL) + +/* + * Allow to use the 'data' or 'string' keyword in hashlib.new() + * and other hash functions named constructors. + * + * - If 'data' and 'string' are both non-NULL, set an exception and return -1. + * - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0. + * - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation + * warning is set when 'string' is specified. + * + * The symbol is exported for '_hashlib' and HACL*-based extension modules. + */ +PyAPI_FUNC(int) +_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string); + +#endif // !_HASHLIB_HASHLIB_BUFFER_H diff --git a/Modules/_hashlib/hashlib_fetch.h b/Modules/_hashlib/hashlib_fetch.h new file mode 100644 index 00000000000000..a62b8de2a206e6 --- /dev/null +++ b/Modules/_hashlib/hashlib_fetch.h @@ -0,0 +1,127 @@ +/* + * Interface for fetching a message digest from a digest-like identifier. + * + * The following table summaries the possible algorthms: + * + * +----------+--------------+--------------+---------------------------------+ + * | Family | Algorithm | Python Name | Notes | + * +==========+==============+==============+=================================+ + * | MD @ | + * | +--------------+--------------+---------------------------------+ + * | | MD5 | "md5" | | + * +----------+--------------+--------------+---------------------------------+ + * | SHA1 @ | + * | +--------------+--------------+---------------------------------+ + * | | SHA1-160 | "sha1" | | + * +----------+--------------+--------------+---------------------------------+ + * | SHA2 @ | + * | +--------------+--------------+---------------------------------+ + * | | SHA2-224 | "sha224" | | + * | | SHA2-256 | "sha256" | | + * | | SHA2-384 | "sha384" | | + * | | SHA2-512 | "sha512" | | + * +----------+--------------+--------------+---------------------------------+ + * | SHA2t @ Truncated SHA2-512 | + * | +--------------+--------------+---------------------------------+ + * | | SHA2-512/224 | "sha512_224" | | + * | | SHA2-512/256 | "sha512_256" | | + * +----------+--------------+--------------+---------------------------------+ + * | SHA3 @ | + * | +--------------+--------------+---------------------------------+ + * | | SHA3-224 | "sha3_224" | | + * | | SHA3-256 | "sha3_256" | | + * | | SHA3-384 | "sha3_384" | | + * | | SHA3-512 | "sha3_512" | | + * +----------+--------------+--------------+---------------------------------+ + * | SHA3-XOF @ Extensible Output Functions | + * | +--------------+--------------+---------------------------------+ + * | | SHAKE-128 | "shake_128" | | + * | | SHAKE-256 | "shake_256" | | + * +----------+--------------+--------------+---------------------------------+ + * | BLAKE2 @ | + * | +--------------+--------------+---------------------------------+ + * | | BLAKE2b | "blake2b" | | + * | | BLAKE2s | "blake2s" | | + * +----------+--------------+--------------+---------------------------------+ + */ + +#ifndef _HASHLIB_HASHLIB_FETCH_H +#define _HASHLIB_HASHLIB_FETCH_H + +#include "Python.h" + +/* + * Internal error messages used for reporting an unsupported hash algorithm. + * The algorithm can be given by its name, a callable or a PEP-247 module. + * The same message is raised by Lib/hashlib.py::__get_builtin_constructor() + * and _hmacmodule.c::find_hash_info(). + */ +#define _Py_HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S" +#define _Py_HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s" + +#define _Py_HASHLIB_MD_OID(ID) _Py_hashlib_MD_OID_ ## ID + +typedef enum { + /* MD-family */ + _Py_HASHLIB_MD_OID(md5) = 0, + /* SHA-1 family */ + _Py_HASHLIB_MD_OID(sha1), + /* SHA-2 family */ + _Py_HASHLIB_MD_OID(sha224), + _Py_HASHLIB_MD_OID(sha256), + _Py_HASHLIB_MD_OID(sha384), + _Py_HASHLIB_MD_OID(sha512), + /* Truncated SHA-2 family */ + _Py_HASHLIB_MD_OID(sha512_224), + _Py_HASHLIB_MD_OID(sha512_256), + /* SHA-3 family */ + _Py_HASHLIB_MD_OID(sha3_224), + _Py_HASHLIB_MD_OID(sha3_256), + _Py_HASHLIB_MD_OID(sha3_384), + _Py_HASHLIB_MD_OID(sha3_512), + /* SHA-3 XOF SHAKE family */ + _Py_HASHLIB_MD_OID(shake_128), + _Py_HASHLIB_MD_OID(shake_256), + /* BLAKE-2 family */ + _Py_HASHLIB_MD_OID(blake2b), + _Py_HASHLIB_MD_OID(blake2s), +} _Py_hashlib_MD_OID; + +static const char *_Py_HASHLIB_MD_NAMES[] = { +#define DECL_MESSAGE_DIGEST_NAME(ID) [_Py_HASHLIB_MD_OID(ID)] = #ID + /* MD-family */ + DECL_MESSAGE_DIGEST_NAME(md5), + /* SHA-1 family */ + DECL_MESSAGE_DIGEST_NAME(sha1), + /* SHA-2 family */ + DECL_MESSAGE_DIGEST_NAME(sha224), + DECL_MESSAGE_DIGEST_NAME(sha256), + DECL_MESSAGE_DIGEST_NAME(sha384), + DECL_MESSAGE_DIGEST_NAME(sha512), + /* Truncated SHA-2 family */ + DECL_MESSAGE_DIGEST_NAME(sha512_224), + DECL_MESSAGE_DIGEST_NAME(sha512_256), + /* SHA-3 family */ + DECL_MESSAGE_DIGEST_NAME(sha3_224), + DECL_MESSAGE_DIGEST_NAME(sha3_256), + DECL_MESSAGE_DIGEST_NAME(sha3_384), + DECL_MESSAGE_DIGEST_NAME(sha3_512), + /* SHA-3 XOF SHAKE family */ + DECL_MESSAGE_DIGEST_NAME(shake_128), + DECL_MESSAGE_DIGEST_NAME(shake_256), + /* BLAKE-2 family */ + DECL_MESSAGE_DIGEST_NAME(blake2b), + DECL_MESSAGE_DIGEST_NAME(blake2s), +#undef DECL_MESSAGE_DIGEST_NAME + NULL /* sentinel */ +}; + +static inline const char * +_Py_hashlib_md_name(_Py_hashlib_MD_OID id) +{ + assert(id >= 0); + assert(id < Py_ARRAY_LENGTH(_Py_HASHLIB_MD_NAMES)); + return _Py_HASHLIB_MD_NAMES[id]; +} + +#endif // !_HASHLIB_HASHLIB_FETCH_H diff --git a/Modules/hashlib.h b/Modules/_hashlib/hashlib_mutex.h similarity index 53% rename from Modules/hashlib.h rename to Modules/_hashlib/hashlib_mutex.h index 5de5922c345047..d6924a2ef61e81 100644 --- a/Modules/hashlib.h +++ b/Modules/_hashlib/hashlib_mutex.h @@ -1,45 +1,14 @@ -/* Common code for use by all hashlib related modules. */ +#ifndef _HASHLIB_HASHLIB_MUTEX_H +#define _HASHLIB_HASHLIB_MUTEX_H -#include "pycore_lock.h" // PyMutex +#include "Python.h" +#include "pycore_lock.h" // PyMutex /* - * Internal error messages used for reporting an unsupported hash algorithm. - * The algorithm can be given by its name, a callable or a PEP-247 module. - * The same message is raised by Lib/hashlib.py::__get_builtin_constructor() - * and _hmacmodule.c::find_hash_info(). - */ -#define HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S" -#define HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s" - -/* - * Given a PyObject* obj, fill in the Py_buffer* viewp with the result - * of PyObject_GetBuffer. Sets an exception and issues the erraction - * on any errors, e.g. 'return NULL' or 'goto error'. + * Message length above which the GIL is to be released + * when performing hashing operations. */ -#define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \ - if (PyUnicode_Check((obj))) { \ - PyErr_SetString(PyExc_TypeError, \ - "Strings must be encoded before hashing");\ - erraction; \ - } \ - if (!PyObject_CheckBuffer((obj))) { \ - PyErr_SetString(PyExc_TypeError, \ - "object supporting the buffer API required"); \ - erraction; \ - } \ - if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \ - erraction; \ - } \ - if ((viewp)->ndim > 1) { \ - PyErr_SetString(PyExc_BufferError, \ - "Buffer must be single dimension"); \ - PyBuffer_Release((viewp)); \ - erraction; \ - } \ - } while(0) - -#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \ - GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL) +#define HASHLIB_GIL_MINSIZE 2048 /* * Helper code to synchronize access to the hash object when the GIL is @@ -64,12 +33,6 @@ #define HASHLIB_ACQUIRE_LOCK(OBJ) PyMutex_Lock(&(OBJ)->mutex) #define HASHLIB_RELEASE_LOCK(OBJ) PyMutex_Unlock(&(OBJ)->mutex) -/* - * Message length above which the GIL is to be released - * when performing hashing operations. - */ -#define HASHLIB_GIL_MINSIZE 2048 - // Macros for executing code while conditionally holding the GIL. // // These only drop the GIL if the lock acquisition itself is likely to @@ -116,41 +79,4 @@ } \ } while (0) -static inline int -_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string) -{ - if (data != NULL && string == NULL) { - // called as H(data) or H(data=...) - *res = data; - return 1; - } - else if (data == NULL && string != NULL) { - // called as H(string=...) - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "the 'string' keyword parameter is deprecated since " - "Python 3.15 and slated for removal in Python 3.19; " - "use the 'data' keyword parameter or pass the data " - "to hash as a positional argument instead", 1) < 0) - { - *res = NULL; - return -1; - } - *res = string; - return 1; - } - else if (data == NULL && string == NULL) { - // fast path when no data is given - assert(!PyErr_Occurred()); - *res = NULL; - return 0; - } - else { - // called as H(data=..., string) - *res = NULL; - PyErr_SetString(PyExc_TypeError, - "'data' and 'string' are mutually exclusive " - "and support for 'string' keyword parameter " - "is slated for removal in a future version."); - return -1; - } -} +#endif // !_HASHLIB_HASHLIB_MUTEX_H From 854bf43ebcc86a5a7726b3f0e60ea8fa3aab4efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:23:33 +0200 Subject: [PATCH 02/10] update usage of `hashlib.h` --- Modules/_hashopenssl.c | 9 ++++++--- Modules/blake2module.c | 6 ++++-- Modules/hmacmodule.c | 8 +++++--- Modules/md5module.c | 3 ++- Modules/sha1module.c | 4 +++- Modules/sha2module.c | 5 +++-- Modules/sha3module.c | 4 +++- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index d79e4b360e95c5..c42513a53d4561 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -26,7 +26,10 @@ #include "pycore_hashtable.h" #include "pycore_strhex.h" // _Py_strhex() #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED -#include "hashlib.h" + +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_fetch.h" +#include "_hashlib/hashlib_mutex.h" /* EVP is the preferred interface to hashing in OpenSSL */ #include @@ -532,7 +535,7 @@ raise_unsupported_algorithm_error(_hashlibstate *state, PyObject *digestmod) { raise_unsupported_algorithm_impl( state->unsupported_digestmod_error, - HASHLIB_UNSUPPORTED_ALGORITHM, + _Py_HASHLIB_UNSUPPORTED_ALGORITHM, digestmod ); } @@ -542,7 +545,7 @@ raise_unsupported_str_algorithm_error(_hashlibstate *state, const char *name) { raise_unsupported_algorithm_impl( state->unsupported_digestmod_error, - HASHLIB_UNSUPPORTED_STR_ALGORITHM, + _Py_HASHLIB_UNSUPPORTED_STR_ALGORITHM, name ); } diff --git a/Modules/blake2module.c b/Modules/blake2module.c index 163f238a4268d0..5eaa9962e010b2 100644 --- a/Modules/blake2module.c +++ b/Modules/blake2module.c @@ -15,10 +15,12 @@ #endif #include "Python.h" -#include "hashlib.h" +#include "pycore_moduleobject.h" #include "pycore_strhex.h" // _Py_strhex() #include "pycore_typeobject.h" -#include "pycore_moduleobject.h" + +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_mutex.h" // QUICK CPU AUTODETECTION // diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index b5405c99f1f8ce..1752d0593c46f2 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -20,6 +20,10 @@ #include "pycore_hashtable.h" #include "pycore_strhex.h" // _Py_strhex() +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_fetch.h" +#include "_hashlib/hashlib_mutex.h" + /* * Taken from blake2module.c. In the future, detection of SIMD support * should be delegated to https://github.com/python/cpython/pull/125011. @@ -47,8 +51,6 @@ #include -#include "hashlib.h" - // --- Reusable error messages ------------------------------------------------ static inline void @@ -656,7 +658,7 @@ find_hash_info(hmacmodule_state *state, PyObject *hash_info_ref) } if (rc == 0) { PyErr_Format(state->unknown_hash_error, - HASHLIB_UNSUPPORTED_ALGORITHM, hash_info_ref); + _Py_HASHLIB_UNSUPPORTED_ALGORITHM, hash_info_ref); return NULL; } assert(info != NULL); diff --git a/Modules/md5module.c b/Modules/md5module.c index 8b6dd4a8195dfb..d56388f8d95bd5 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -24,7 +24,8 @@ #include "Python.h" #include "pycore_strhex.h" // _Py_strhex() -#include "hashlib.h" +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_mutex.h" #include "_hacl/Hacl_Hash_MD5.h" diff --git a/Modules/sha1module.c b/Modules/sha1module.c index faa9dcccc5755b..07d8f0b52f49f1 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -20,10 +20,12 @@ #endif #include "Python.h" -#include "hashlib.h" #include "pycore_strhex.h" // _Py_strhex() #include "pycore_typeobject.h" // _PyType_GetModuleState() +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_mutex.h" + #include "_hacl/Hacl_Hash_SHA1.h" /* The SHA1 block size and message digest sizes, in bytes */ diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 36300ba899fd44..2cafefc54c32f9 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -22,10 +22,11 @@ #include "Python.h" #include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_typeobject.h" // _PyType_GetModuleState() #include "pycore_strhex.h" // _Py_strhex() +#include "pycore_typeobject.h" // _PyType_GetModuleState() -#include "hashlib.h" +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_mutex.h" #include "_hacl/Hacl_Hash_SHA2.h" diff --git a/Modules/sha3module.c b/Modules/sha3module.c index 5764556bb680f3..55820d7b8db95c 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -23,7 +23,9 @@ #include "Python.h" #include "pycore_strhex.h" // _Py_strhex() #include "pycore_typeobject.h" // _PyType_GetModuleState() -#include "hashlib.h" + +#include "_hashlib/hashlib_buffer.h" +#include "_hashlib/hashlib_mutex.h" #include "_hacl/Hacl_Hash_SHA3.h" From e1d233e6e8dfe365ba268798e6dc37fcb311e400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:30:34 +0200 Subject: [PATCH 03/10] update build configuration --- Makefile.pre.in | 37 ++++++++++++++++++++----- PCbuild/_hashlib.vcxproj | 6 +++++ PCbuild/_hashlib.vcxproj.filters | 2 +- PCbuild/pythoncore.vcxproj | 4 +++ PCbuild/pythoncore.vcxproj.filters | 12 +++++++++ Tools/c-analyzer/cpython/ignored.tsv | 1 + configure | 40 ++++++++++++++++++---------- configure.ac | 17 ++++++++++-- 8 files changed, 95 insertions(+), 24 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index fa17f5d7bfc0ac..9582b002320b37 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -227,6 +227,7 @@ ENSUREPIP= @ENSUREPIP@ # Internal static libraries LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a LIBEXPAT_A= Modules/expat/libexpat.a +LIBHASHLIB_INTERNAL_A=Modules/_hashlib/libhashlib.a # HACL* build configuration LIBHACL_CFLAGS=@LIBHACL_CFLAGS@ @@ -761,6 +762,17 @@ LIBHACL_HMAC_HEADERS= \ $(LIBHACL_BLAKE2_HEADERS) \ $(LIBHACL_HEADERS) +########################################################################## +# Internal library for cryptographic primitives + +LIBHASHLIB_INTERNAL_OBJS= \ + Modules/_hashlib/hashlib_buffer.o + +LIBHASHLIB_INTERNAL_HEADERS= \ + Modules/_hashlib/hashlib_buffer.h \ + Modules/_hashlib/hashlib_fetch.h \ + Modules/_hashlib/hashlib_mutex.h + ######################################################################### # Rules @@ -1511,6 +1523,17 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBEXPAT_OBJS) +########################################################################## +# '_hashlib', '_hmac' and HACL*-based modules helpers +LIBHASHLIB_INTERNAL_CFLAGS=@LIBHASHLIB_INTERNAL_CFLAGS@ $(PY_STDMODULE_CFLAGS) $(CCSHARED) + +Modules/_hashlib/hashlib_buffer.o: Modules/_hashlib/hashlib_buffer.c $(LIBHASHLIB_INTERNAL_HEADERS) $(PYTHON_HEADERS) + $(CC) -I$(srcdir)/Modules/_hashlib -c $(LIBHASHLIB_INTERNAL_CFLAGS) -o $@ $(srcdir)/Modules/_hashlib/hashlib_buffer.c + +$(LIBHASHLIB_INTERNAL_A): $(LIBHASHLIB_INTERNAL_OBJS) + -rm -f $@ + $(AR) $(ARFLAGS) $@ $(LIBHASHLIB_INTERNAL_OBJS) + ########################################################################## # HACL* library build # @@ -3353,21 +3376,21 @@ MODULE__CTYPES_TEST_DEPS=$(srcdir)/Modules/_ctypes/_ctypes_test_generated.c.h MODULE__CTYPES_MALLOC_CLOSURE=@MODULE__CTYPES_MALLOC_CLOSURE@ MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h @LIBMPDEC_INTERNAL@ MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/pyexpat.c @LIBEXPAT_INTERNAL@ -MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h +MODULE__HASHLIB_DEPS=@LIBHASHLIB_INTERNAL@ MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h # HACL*-based cryptographic primitives -MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_MD5_HEADERS) $(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__MD5_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_MD5_HEADERS) $(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__MD5_LDEPS=$(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@) -MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA1_HEADERS) $(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__SHA1_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA1_HEADERS) $(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__SHA1_LDEPS=$(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@) -MODULE__SHA2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__SHA2_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__SHA2_LDEPS=$(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@) -MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA3_HEADERS) $(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__SHA3_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA3_HEADERS) $(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__SHA3_LDEPS=$(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@) -MODULE__BLAKE2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_BLAKE2_HEADERS) $(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__BLAKE2_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_BLAKE2_HEADERS) $(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__BLAKE2_LDEPS=$(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@) -MODULE__HMAC_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HMAC_HEADERS) $(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@) +MODULE__HMAC_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_HMAC_HEADERS) $(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__HMAC_LDEPS=$(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@) MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c diff --git a/PCbuild/_hashlib.vcxproj b/PCbuild/_hashlib.vcxproj index 2cd205224bc089..9e6dcee40793d3 100644 --- a/PCbuild/_hashlib.vcxproj +++ b/PCbuild/_hashlib.vcxproj @@ -100,6 +100,12 @@ + + + + + + diff --git a/PCbuild/_hashlib.vcxproj.filters b/PCbuild/_hashlib.vcxproj.filters index 7a0700c007f644..d465d92a956eda 100644 --- a/PCbuild/_hashlib.vcxproj.filters +++ b/PCbuild/_hashlib.vcxproj.filters @@ -18,4 +18,4 @@ Resource Files - \ No newline at end of file + diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b911c9385634d7..7fbb8f9dc7609c 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -447,6 +447,10 @@ HACL_CAN_COMPILE_VEC128;%(PreprocessorDefinitions) /arch:AVX %(AdditionalOptions) + + + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 0e6d42cc959ba5..088c99eab01b61 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -255,6 +255,15 @@ Include + + Modules\_hashlib + + + Modules\_hashlib + + + Modules\_hashlib + Modules @@ -971,6 +980,9 @@ Modules + + Modules\_hashlib + Modules diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index dc626e4bea0f59..de24325fb63838 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -238,6 +238,7 @@ Modules/_decimal/_decimal.c - signal_map_template - Modules/_decimal/_decimal.c - ssize_constants - Modules/_decimal/_decimal.c - INVALID_SIGNALDICT_ERROR_MSG - Modules/_elementtree.c - ExpatMemoryHandler - +Modules/_hashlib/hashlib_fetch.h - _Py_HASHLIB_MD_NAMES - Modules/_hashopenssl.c - py_hashes - Modules/_hacl/Hacl_Hash_SHA1.c - _h0 - Modules/_hacl/Hacl_Hash_MD5.c - _h0 - diff --git a/configure b/configure index 8db2e9c46abba2..aa5223f1d77a24 100755 --- a/configure +++ b/configure @@ -725,6 +725,8 @@ LIBHACL_BLAKE2_SIMD128_OBJS LIBHACL_SIMD128_FLAGS LIBHACL_LDFLAGS LIBHACL_CFLAGS +LIBHASHLIB_INTERNAL +LIBHASHLIB_INTERNAL_CFLAGS MODULE_UNICODEDATA_FALSE MODULE_UNICODEDATA_TRUE MODULE__MULTIBYTECODEC_FALSE @@ -29947,6 +29949,7 @@ SRCDIRS="\ Modules/_decimal \ Modules/_decimal/libmpdec \ Modules/_hacl \ + Modules/_hashlib \ Modules/_io \ Modules/_multiprocessing \ Modules/_sqlite \ @@ -32523,6 +32526,15 @@ then : fi +############################################################################### +# Cryptographic primitives +LIBHASHLIB_INTERNAL_CFLAGS="-I\$(srcdir)/Modules/_hashlib" +LIBHASHLIB_INTERNAL_LDFLAGS="-lm \$(LIBHASHLIB_INTERNAL_A)" +LIBHASHLIB_INTERNAL="\$(LIBHASHLIB_INTERNAL_HEADERS) \$(LIBHASHLIB_INTERNAL_A)" + + + + ############################################################################### # HACL* compilation and linking configuration (contact: @picnixz) # @@ -32771,8 +32783,8 @@ fi if test "x$py_cv_module__md5" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__MD5_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__MD5_LDFLAGS=\$($LIBHACL_MD5_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__MD5_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__MD5_LDFLAGS=\$($LIBHACL_MD5_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__md5" = yes; then @@ -32816,8 +32828,8 @@ fi if test "x$py_cv_module__sha1" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__SHA1_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA1_LDFLAGS=\$($LIBHACL_SHA1_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA1_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA1_LDFLAGS=\$($LIBHACL_SHA1_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__sha1" = yes; then @@ -32861,8 +32873,8 @@ fi if test "x$py_cv_module__sha2" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__SHA2_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA2_LDFLAGS=\$($LIBHACL_SHA2_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA2_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA2_LDFLAGS=\$($LIBHACL_SHA2_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__sha2" = yes; then @@ -32906,8 +32918,8 @@ fi if test "x$py_cv_module__sha3" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__SHA3_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA3_LDFLAGS=\$($LIBHACL_SHA3_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA3_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA3_LDFLAGS=\$($LIBHACL_SHA3_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__sha3" = yes; then @@ -32951,8 +32963,8 @@ fi if test "x$py_cv_module__blake2" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__BLAKE2_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__BLAKE2_LDFLAGS=\$($LIBHACL_BLAKE2_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__BLAKE2_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__BLAKE2_LDFLAGS=\$($LIBHACL_BLAKE2_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__blake2" = yes; then @@ -32997,8 +33009,8 @@ fi if test "x$py_cv_module__hmac" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__HMAC_CFLAGS=$LIBHACL_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__HMAC_LDFLAGS=\$($LIBHACL_HMAC_LDFLAGS)$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HMAC_CFLAGS=$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HMAC_LDFLAGS=\$($LIBHACL_HMAC_LDFLAGS) $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__hmac" = yes; then @@ -33679,8 +33691,8 @@ fi if test "x$py_cv_module__hashlib" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__HASHLIB_CFLAGS=$OPENSSL_INCLUDES$as_nl" - as_fn_append MODULE_BLOCK "MODULE__HASHLIB_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_CFLAGS=$OPENSSL_INCLUDES $LIBHASHLIB_INTERNAL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS $LIBHASHLIB_INTERNAL_LDFLAGS$as_nl" fi if test "$py_cv_module__hashlib" = yes; then diff --git a/configure.ac b/configure.ac index c839dd65a5fc5a..f05ad35abd71a6 100644 --- a/configure.ac +++ b/configure.ac @@ -7186,6 +7186,7 @@ SRCDIRS="\ Modules/_decimal \ Modules/_decimal/libmpdec \ Modules/_hacl \ + Modules/_hashlib \ Modules/_io \ Modules/_multiprocessing \ Modules/_sqlite \ @@ -7956,6 +7957,15 @@ PY_STDLIB_MOD_SIMPLE([_codecs_tw]) PY_STDLIB_MOD_SIMPLE([_multibytecodec]) PY_STDLIB_MOD_SIMPLE([unicodedata]) +############################################################################### +# Cryptographic primitives +LIBHASHLIB_INTERNAL_CFLAGS="-I\$(srcdir)/Modules/_hashlib" +LIBHASHLIB_INTERNAL_LDFLAGS="-lm \$(LIBHASHLIB_INTERNAL_A)" +LIBHASHLIB_INTERNAL="\$(LIBHASHLIB_INTERNAL_HEADERS) \$(LIBHASHLIB_INTERNAL_A)" + +AC_SUBST([LIBHASHLIB_INTERNAL_CFLAGS]) +AC_SUBST([LIBHASHLIB_INTERNAL]) + ############################################################################### # HACL* compilation and linking configuration (contact: @picnixz) # @@ -8092,7 +8102,9 @@ dnl The EXTNAME is the name of the extension module being built. AC_DEFUN([PY_HACL_CREATE_MODULE], [ AS_VAR_PUSHDEF([v], [[LIBHACL_][$1][_LDFLAGS]]) AS_VAR_SET([v], [[LIBHACL_][$1][_LIB_${LIBHACL_LDEPS_LIBTYPE}]]) - PY_STDLIB_MOD([$2], [$3], [], [$LIBHACL_CFLAGS], [\$($v)]) + PY_STDLIB_MOD([$2], [$3], [], + [$LIBHACL_CFLAGS $LIBHASHLIB_INTERNAL_CFLAGS], + [\$($v) $LIBHASHLIB_INTERNAL_LDFLAGS]) AS_VAR_POPDEF([v]) ]) @@ -8173,7 +8185,8 @@ dnl OpenSSL bindings PY_STDLIB_MOD([_ssl], [], [test "$ac_cv_working_openssl_ssl" = yes], [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS]) PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], - [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS]) + [$OPENSSL_INCLUDES $LIBHASHLIB_INTERNAL_CFLAGS], + [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS $LIBHASHLIB_INTERNAL_LDFLAGS]) dnl test modules PY_STDLIB_MOD([_testcapi], From 59b0cda0b18ccd667a0302269e1c50590ac51606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:47:49 +0200 Subject: [PATCH 04/10] blurb --- .../next/Build/2025-07-22-14-47-45.gh-issue-131876.oaYEEP.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Build/2025-07-22-14-47-45.gh-issue-131876.oaYEEP.rst diff --git a/Misc/NEWS.d/next/Build/2025-07-22-14-47-45.gh-issue-131876.oaYEEP.rst b/Misc/NEWS.d/next/Build/2025-07-22-14-47-45.gh-issue-131876.oaYEEP.rst new file mode 100644 index 00000000000000..304f2c30f664db --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-07-22-14-47-45.gh-issue-131876.oaYEEP.rst @@ -0,0 +1,2 @@ +Remove :file:`!Modules/hashlib.h` and move its content into dedicated files +now located in ``Modules/_hashlib``. Patch by Bénédikt Tran. From 42636888f368802781c59ab0cc8c8e0fe4869bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 26 Jul 2025 09:02:59 +0200 Subject: [PATCH 05/10] remove code that is currently unused --- Modules/_hashlib/hashlib_fetch.h | 65 -------------------------------- 1 file changed, 65 deletions(-) diff --git a/Modules/_hashlib/hashlib_fetch.h b/Modules/_hashlib/hashlib_fetch.h index a62b8de2a206e6..c1479e96148df6 100644 --- a/Modules/_hashlib/hashlib_fetch.h +++ b/Modules/_hashlib/hashlib_fetch.h @@ -59,69 +59,4 @@ #define _Py_HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S" #define _Py_HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s" -#define _Py_HASHLIB_MD_OID(ID) _Py_hashlib_MD_OID_ ## ID - -typedef enum { - /* MD-family */ - _Py_HASHLIB_MD_OID(md5) = 0, - /* SHA-1 family */ - _Py_HASHLIB_MD_OID(sha1), - /* SHA-2 family */ - _Py_HASHLIB_MD_OID(sha224), - _Py_HASHLIB_MD_OID(sha256), - _Py_HASHLIB_MD_OID(sha384), - _Py_HASHLIB_MD_OID(sha512), - /* Truncated SHA-2 family */ - _Py_HASHLIB_MD_OID(sha512_224), - _Py_HASHLIB_MD_OID(sha512_256), - /* SHA-3 family */ - _Py_HASHLIB_MD_OID(sha3_224), - _Py_HASHLIB_MD_OID(sha3_256), - _Py_HASHLIB_MD_OID(sha3_384), - _Py_HASHLIB_MD_OID(sha3_512), - /* SHA-3 XOF SHAKE family */ - _Py_HASHLIB_MD_OID(shake_128), - _Py_HASHLIB_MD_OID(shake_256), - /* BLAKE-2 family */ - _Py_HASHLIB_MD_OID(blake2b), - _Py_HASHLIB_MD_OID(blake2s), -} _Py_hashlib_MD_OID; - -static const char *_Py_HASHLIB_MD_NAMES[] = { -#define DECL_MESSAGE_DIGEST_NAME(ID) [_Py_HASHLIB_MD_OID(ID)] = #ID - /* MD-family */ - DECL_MESSAGE_DIGEST_NAME(md5), - /* SHA-1 family */ - DECL_MESSAGE_DIGEST_NAME(sha1), - /* SHA-2 family */ - DECL_MESSAGE_DIGEST_NAME(sha224), - DECL_MESSAGE_DIGEST_NAME(sha256), - DECL_MESSAGE_DIGEST_NAME(sha384), - DECL_MESSAGE_DIGEST_NAME(sha512), - /* Truncated SHA-2 family */ - DECL_MESSAGE_DIGEST_NAME(sha512_224), - DECL_MESSAGE_DIGEST_NAME(sha512_256), - /* SHA-3 family */ - DECL_MESSAGE_DIGEST_NAME(sha3_224), - DECL_MESSAGE_DIGEST_NAME(sha3_256), - DECL_MESSAGE_DIGEST_NAME(sha3_384), - DECL_MESSAGE_DIGEST_NAME(sha3_512), - /* SHA-3 XOF SHAKE family */ - DECL_MESSAGE_DIGEST_NAME(shake_128), - DECL_MESSAGE_DIGEST_NAME(shake_256), - /* BLAKE-2 family */ - DECL_MESSAGE_DIGEST_NAME(blake2b), - DECL_MESSAGE_DIGEST_NAME(blake2s), -#undef DECL_MESSAGE_DIGEST_NAME - NULL /* sentinel */ -}; - -static inline const char * -_Py_hashlib_md_name(_Py_hashlib_MD_OID id) -{ - assert(id >= 0); - assert(id < Py_ARRAY_LENGTH(_Py_HASHLIB_MD_NAMES)); - return _Py_HASHLIB_MD_NAMES[id]; -} - #endif // !_HASHLIB_HASHLIB_FETCH_H From eb817fd57facb93a10845b314e578c73f843e61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 26 Jul 2025 09:03:04 +0200 Subject: [PATCH 06/10] cleanup imports --- Modules/_hashopenssl.c | 6 +++--- Modules/blake2module.c | 2 +- Modules/md5module.c | 2 +- Modules/sha1module.c | 4 ++-- Modules/sha2module.c | 6 +++--- Modules/sha3module.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index c42513a53d4561..c5d101289af1e7 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -24,8 +24,8 @@ #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 "pycore_strhex.h" // _Py_strhex() +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED #include "_hashlib/hashlib_buffer.h" #include "_hashlib/hashlib_fetch.h" @@ -34,7 +34,7 @@ /* EVP is the preferred interface to hashing in OpenSSL */ #include #include -#include // FIPS_mode() +#include // FIPS_mode() /* We use the object interface to discover what hashes OpenSSL supports. */ #include #include diff --git a/Modules/blake2module.c b/Modules/blake2module.c index 5eaa9962e010b2..13c969056be354 100644 --- a/Modules/blake2module.c +++ b/Modules/blake2module.c @@ -16,7 +16,7 @@ #include "Python.h" #include "pycore_moduleobject.h" -#include "pycore_strhex.h" // _Py_strhex() +#include "pycore_strhex.h" // _Py_strhex() #include "pycore_typeobject.h" #include "_hashlib/hashlib_buffer.h" diff --git a/Modules/md5module.c b/Modules/md5module.c index d56388f8d95bd5..d5dc4f60a575d4 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -22,7 +22,7 @@ #endif #include "Python.h" -#include "pycore_strhex.h" // _Py_strhex() +#include "pycore_strhex.h" // _Py_strhex() #include "_hashlib/hashlib_buffer.h" #include "_hashlib/hashlib_mutex.h" diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 07d8f0b52f49f1..86e5691e8463e4 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -20,8 +20,8 @@ #endif #include "Python.h" -#include "pycore_strhex.h" // _Py_strhex() -#include "pycore_typeobject.h" // _PyType_GetModuleState() +#include "pycore_strhex.h" // _Py_strhex() +#include "pycore_typeobject.h" // _PyType_GetModuleState() #include "_hashlib/hashlib_buffer.h" #include "_hashlib/hashlib_mutex.h" diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 2cafefc54c32f9..dbf6dde1b8c121 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -21,9 +21,9 @@ #endif #include "Python.h" -#include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_strhex.h" // _Py_strhex() -#include "pycore_typeobject.h" // _PyType_GetModuleState() +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_strhex.h" // _Py_strhex() +#include "pycore_typeobject.h" // _PyType_GetModuleState() #include "_hashlib/hashlib_buffer.h" #include "_hashlib/hashlib_mutex.h" diff --git a/Modules/sha3module.c b/Modules/sha3module.c index 55820d7b8db95c..c67bfadbe4664a 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -21,8 +21,8 @@ #endif #include "Python.h" -#include "pycore_strhex.h" // _Py_strhex() -#include "pycore_typeobject.h" // _PyType_GetModuleState() +#include "pycore_strhex.h" // _Py_strhex() +#include "pycore_typeobject.h" // _PyType_GetModuleState() #include "_hashlib/hashlib_buffer.h" #include "_hashlib/hashlib_mutex.h" From 06d2c87e7144de356570e5076d22417a57a3c0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:10:14 +0200 Subject: [PATCH 07/10] amend comments --- Modules/_hashlib/hashlib_fetch.h | 45 +------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/Modules/_hashlib/hashlib_fetch.h b/Modules/_hashlib/hashlib_fetch.h index c1479e96148df6..09add71e0c798c 100644 --- a/Modules/_hashlib/hashlib_fetch.h +++ b/Modules/_hashlib/hashlib_fetch.h @@ -1,48 +1,5 @@ /* - * Interface for fetching a message digest from a digest-like identifier. - * - * The following table summaries the possible algorthms: - * - * +----------+--------------+--------------+---------------------------------+ - * | Family | Algorithm | Python Name | Notes | - * +==========+==============+==============+=================================+ - * | MD @ | - * | +--------------+--------------+---------------------------------+ - * | | MD5 | "md5" | | - * +----------+--------------+--------------+---------------------------------+ - * | SHA1 @ | - * | +--------------+--------------+---------------------------------+ - * | | SHA1-160 | "sha1" | | - * +----------+--------------+--------------+---------------------------------+ - * | SHA2 @ | - * | +--------------+--------------+---------------------------------+ - * | | SHA2-224 | "sha224" | | - * | | SHA2-256 | "sha256" | | - * | | SHA2-384 | "sha384" | | - * | | SHA2-512 | "sha512" | | - * +----------+--------------+--------------+---------------------------------+ - * | SHA2t @ Truncated SHA2-512 | - * | +--------------+--------------+---------------------------------+ - * | | SHA2-512/224 | "sha512_224" | | - * | | SHA2-512/256 | "sha512_256" | | - * +----------+--------------+--------------+---------------------------------+ - * | SHA3 @ | - * | +--------------+--------------+---------------------------------+ - * | | SHA3-224 | "sha3_224" | | - * | | SHA3-256 | "sha3_256" | | - * | | SHA3-384 | "sha3_384" | | - * | | SHA3-512 | "sha3_512" | | - * +----------+--------------+--------------+---------------------------------+ - * | SHA3-XOF @ Extensible Output Functions | - * | +--------------+--------------+---------------------------------+ - * | | SHAKE-128 | "shake_128" | | - * | | SHAKE-256 | "shake_256" | | - * +----------+--------------+--------------+---------------------------------+ - * | BLAKE2 @ | - * | +--------------+--------------+---------------------------------+ - * | | BLAKE2b | "blake2b" | | - * | | BLAKE2s | "blake2s" | | - * +----------+--------------+--------------+---------------------------------+ + * Utilities used when fetching a message digest from a digest-like identifier. */ #ifndef _HASHLIB_HASHLIB_FETCH_H From a1a2f1bed381014ab194ab331dca3cd402af4b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:13:36 +0200 Subject: [PATCH 08/10] remove unused rules --- Tools/c-analyzer/cpython/ignored.tsv | 1 - 1 file changed, 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index de24325fb63838..dc626e4bea0f59 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -238,7 +238,6 @@ Modules/_decimal/_decimal.c - signal_map_template - Modules/_decimal/_decimal.c - ssize_constants - Modules/_decimal/_decimal.c - INVALID_SIGNALDICT_ERROR_MSG - Modules/_elementtree.c - ExpatMemoryHandler - -Modules/_hashlib/hashlib_fetch.h - _Py_HASHLIB_MD_NAMES - Modules/_hashopenssl.c - py_hashes - Modules/_hacl/Hacl_Hash_SHA1.c - _h0 - Modules/_hacl/Hacl_Hash_MD5.c - _h0 - From 89c0e3c1888064c9fe74e5ed15135e896da11cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:32:30 +0200 Subject: [PATCH 09/10] reduce exported scope --- Modules/_hashlib/hashlib_buffer.c | 25 +++++++++++++++ Modules/_hashlib/hashlib_buffer.h | 52 +++++++++---------------------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/Modules/_hashlib/hashlib_buffer.c b/Modules/_hashlib/hashlib_buffer.c index 34811c6266fd64..032f93ad53ad1b 100644 --- a/Modules/_hashlib/hashlib_buffer.c +++ b/Modules/_hashlib/hashlib_buffer.c @@ -38,3 +38,28 @@ _Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string) return -1; } } + +int +_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view) +{ + if (PyUnicode_Check(obj)) { + PyErr_SetString(PyExc_TypeError, + "Strings must be encoded before hashing"); + return -1; + } + if (!PyObject_CheckBuffer(obj)) { + PyErr_SetString(PyExc_TypeError, + "object supporting the buffer API required"); + return -1; + } + if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) { + return -1; + } + if (view->ndim > 1) { + PyErr_SetString(PyExc_BufferError, + "Buffer must be single dimension"); + PyBuffer_Release(view); + return -1; + } + return 0; +} diff --git a/Modules/_hashlib/hashlib_buffer.h b/Modules/_hashlib/hashlib_buffer.h index 74ef20968f1c6b..585ae10566f134 100644 --- a/Modules/_hashlib/hashlib_buffer.h +++ b/Modules/_hashlib/hashlib_buffer.h @@ -3,36 +3,26 @@ #include "Python.h" +/* + * Allow to use the 'data' or 'string' keyword in hashlib.new() + * and other hash functions named constructors. + * + * - If 'data' and 'string' are both non-NULL, set an exception and return -1. + * - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0. + * - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation + * warning is set when 'string' is specified. + */ +extern int +_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string); + /* * Obtain a buffer view from a buffer-like object 'obj'. * * On success, store the result in 'view' and return 0. * On error, set an exception and return -1. */ -static inline int -_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view) -{ - if (PyUnicode_Check(obj)) { - PyErr_SetString(PyExc_TypeError, - "Strings must be encoded before hashing"); - return -1; - } - if (!PyObject_CheckBuffer(obj)) { - PyErr_SetString(PyExc_TypeError, - "object supporting the buffer API required"); - return -1; - } - if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) { - return -1; - } - if (view->ndim > 1) { - PyErr_SetString(PyExc_BufferError, - "Buffer must be single dimension"); - PyBuffer_Release(view); - return -1; - } - return 0; -} +extern int +_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view); /* * Call _Py_hashlib_get_buffer_view() and check if it succeeded. @@ -51,18 +41,4 @@ _Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view) #define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \ GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL) -/* - * Allow to use the 'data' or 'string' keyword in hashlib.new() - * and other hash functions named constructors. - * - * - If 'data' and 'string' are both non-NULL, set an exception and return -1. - * - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0. - * - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation - * warning is set when 'string' is specified. - * - * The symbol is exported for '_hashlib' and HACL*-based extension modules. - */ -PyAPI_FUNC(int) -_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string); - #endif // !_HASHLIB_HASHLIB_BUFFER_H From a0fa84954ae76c912fa5ba9b36fb52983e0267d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:45:57 +0200 Subject: [PATCH 10/10] Windows is not happy --- Modules/_hashlib/hashlib_buffer.h | 8 ++++++-- PCbuild/_hashlib.vcxproj | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Modules/_hashlib/hashlib_buffer.h b/Modules/_hashlib/hashlib_buffer.h index 585ae10566f134..809f19884f41b7 100644 --- a/Modules/_hashlib/hashlib_buffer.h +++ b/Modules/_hashlib/hashlib_buffer.h @@ -11,8 +11,10 @@ * - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0. * - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation * warning is set when 'string' is specified. + * + * The symbol is exported for '_hashlib' and HACL*-based extension modules. */ -extern int +PyAPI_FUNC(int) _Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string); /* @@ -20,8 +22,10 @@ _Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string); * * On success, store the result in 'view' and return 0. * On error, set an exception and return -1. + * + * The symbol is exported for '_hashlib' and HACL*-based extension modules. */ -extern int +PyAPI_FUNC(int) _Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view); /* diff --git a/PCbuild/_hashlib.vcxproj b/PCbuild/_hashlib.vcxproj index 9e6dcee40793d3..cfb43cee935b86 100644 --- a/PCbuild/_hashlib.vcxproj +++ b/PCbuild/_hashlib.vcxproj @@ -101,7 +101,6 @@ -