Skip to content

Commit 487c4b8

Browse files
committed
explode hashlib.h into multiple files
1 parent aafbdb5 commit 487c4b8

File tree

5 files changed

+249
-82
lines changed

5 files changed

+249
-82
lines changed

Modules/_hashlib/hashlib_buffer.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "hashlib_buffer.h"
2+
3+
int
4+
_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string)
5+
{
6+
if (data != NULL && string == NULL) {
7+
// called as H(data) or H(data=...)
8+
*res = data;
9+
return 1;
10+
}
11+
else if (data == NULL && string != NULL) {
12+
// called as H(string=...)
13+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
14+
"the 'string' keyword parameter is deprecated since "
15+
"Python 3.15 and slated for removal in Python 3.19; "
16+
"use the 'data' keyword parameter or pass the data "
17+
"to hash as a positional argument instead", 1) < 0)
18+
{
19+
*res = NULL;
20+
return -1;
21+
}
22+
*res = string;
23+
return 1;
24+
}
25+
else if (data == NULL && string == NULL) {
26+
// fast path when no data is given
27+
assert(!PyErr_Occurred());
28+
*res = NULL;
29+
return 0;
30+
}
31+
else {
32+
// called as H(data=..., string)
33+
*res = NULL;
34+
PyErr_SetString(PyExc_TypeError,
35+
"'data' and 'string' are mutually exclusive "
36+
"and support for 'string' keyword parameter "
37+
"is slated for removal in a future version.");
38+
return -1;
39+
}
40+
}

Modules/_hashlib/hashlib_buffer.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#ifndef _HASHLIB_HASHLIB_BUFFER_H
2+
#define _HASHLIB_HASHLIB_BUFFER_H
3+
4+
#include "Python.h"
5+
6+
/*
7+
* Given an buffer-like OBJ, fill in the buffer VIEW with the result
8+
* of PyObject_GetBuffer.
9+
*
10+
* On error, set an exception and execute the ERRACTION statements,
11+
* e.g. 'return NULL' or 'goto error'.
12+
*
13+
* Parameters
14+
*
15+
* OBJ An object supporting the buffer API.
16+
* VIEW A Py_buffer pointer to fill.
17+
* ERRACTION The statements to execute on error.
18+
*/
19+
#define GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, ERRACTION) \
20+
do { \
21+
if (PyUnicode_Check((OBJ))) { \
22+
PyErr_SetString(PyExc_TypeError, \
23+
"strings must be encoded before hashing"); \
24+
ERRACTION; \
25+
} \
26+
if (!PyObject_CheckBuffer((OBJ))) { \
27+
PyErr_SetString(PyExc_TypeError, \
28+
"object supporting the buffer API required"); \
29+
ERRACTION; \
30+
} \
31+
if (PyObject_GetBuffer((OBJ), (VIEW), PyBUF_SIMPLE) == -1) { \
32+
ERRACTION; \
33+
} \
34+
if ((VIEW)->ndim > 1) { \
35+
PyErr_SetString(PyExc_BufferError, \
36+
"buffer must be one-dimensional"); \
37+
PyBuffer_Release((VIEW)); \
38+
ERRACTION; \
39+
} \
40+
} while(0)
41+
42+
/* Specialization of GET_BUFFER_VIEW_OR_ERROR() returning NULL on error. */
43+
#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \
44+
GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL)
45+
46+
/*
47+
* Allow to use the 'data' or 'string' keyword in hashlib.new()
48+
* and other hash functions named constructors.
49+
*
50+
* - If 'data' and 'string' are both non-NULL, set an exception and return -1.
51+
* - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0.
52+
* - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation
53+
* warning is set when 'string' is specified.
54+
*
55+
* The symbol is exported for '_hashlib' and HACL*-based extension modules.
56+
*/
57+
PyAPI_FUNC(int)
58+
_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string);
59+
60+
#endif // !_HASHLIB_HASHLIB_BUFFER_H

Modules/_hashlib/hashlib_fetch.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "hashlib_fetch.h"

Modules/_hashlib/hashlib_fetch.h

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Interface for fetching a message digest from a digest-like identifier.
3+
*
4+
* The following table summaries the possible algorthms:
5+
*
6+
* +----------+--------------+--------------+---------------------------------+
7+
* | Family | Algorithm | Python Name | Notes |
8+
* +==========+==============+==============+=================================+
9+
* | MD @ |
10+
* | +--------------+--------------+---------------------------------+
11+
* | | MD5 | "md5" | |
12+
* +----------+--------------+--------------+---------------------------------+
13+
* | SHA1 @ |
14+
* | +--------------+--------------+---------------------------------+
15+
* | | SHA1-160 | "sha1" | |
16+
* +----------+--------------+--------------+---------------------------------+
17+
* | SHA2 @ |
18+
* | +--------------+--------------+---------------------------------+
19+
* | | SHA2-224 | "sha224" | |
20+
* | | SHA2-256 | "sha256" | |
21+
* | | SHA2-384 | "sha384" | |
22+
* | | SHA2-512 | "sha512" | |
23+
* +----------+--------------+--------------+---------------------------------+
24+
* | SHA2t @ Truncated SHA2-512 |
25+
* | +--------------+--------------+---------------------------------+
26+
* | | SHA2-512/224 | "sha512_224" | |
27+
* | | SHA2-512/256 | "sha512_256" | |
28+
* +----------+--------------+--------------+---------------------------------+
29+
* | SHA3 @ |
30+
* | +--------------+--------------+---------------------------------+
31+
* | | SHA3-224 | "sha3_224" | |
32+
* | | SHA3-256 | "sha3_256" | |
33+
* | | SHA3-384 | "sha3_384" | |
34+
* | | SHA3-512 | "sha3_512" | |
35+
* +----------+--------------+--------------+---------------------------------+
36+
* | SHA3-XOF @ Extensible Output Functions |
37+
* | +--------------+--------------+---------------------------------+
38+
* | | SHAKE-128 | "shake_128" | |
39+
* | | SHAKE-256 | "shake_256" | |
40+
* +----------+--------------+--------------+---------------------------------+
41+
* | BLAKE2 @ |
42+
* | +--------------+--------------+---------------------------------+
43+
* | | BLAKE2b | "blake2b" | |
44+
* | | BLAKE2s | "blake2s" | |
45+
* +----------+--------------+--------------+---------------------------------+
46+
*/
47+
48+
#ifndef _HASHLIB_HASHLIB_FETCH_H
49+
#define _HASHLIB_HASHLIB_FETCH_H
50+
51+
#include "Python.h"
52+
53+
/*
54+
* Internal error messages used for reporting an unsupported hash algorithm.
55+
* The algorithm can be given by its name, a callable or a PEP-247 module.
56+
* The same message is raised by Lib/hashlib.py::__get_builtin_constructor()
57+
* and _hmacmodule.c::find_hash_info().
58+
*/
59+
#define _Py_HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S"
60+
#define _Py_HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s"
61+
62+
#define _Py_HASHLIB_MD_NAMESPACE(NAME) _Py_hashlib_message_digest_ ## NAME
63+
#define _Py_HASHLIB_MD_FAMILY(ID) _Py_HASHLIB_MD_NAMESPACE(family_ ## ID)
64+
#define _Py_HASHLIB_MD_MEMBER(ID) _Py_HASHLIB_MD_NAMESPACE(member_ ## ID)
65+
66+
#define _Py_HASHLIB_MD_NAMES _Py_HASHLIB_MD_NAMESPACE(NAMES)
67+
#define _Py_HASHLIB_MD_COUNT Py_ARRAY_LENGTH(_Py_HASHLIB_MD_NAMES)
68+
#define _Py_HASHLIB_MD_NAME(MEMBER_ID) \
69+
( \
70+
assert(_Py_HASHLIB_MD_MEMBER(MEMBER_ID) >= 0), \
71+
assert(_Py_HASHLIB_MD_MEMBER(MEMBER_ID) < _Py_HASHLIB_MD_COUNT), \
72+
_Py_HASHLIB_MD_NAMES[_Py_HASHLIB_MD_MEMBER(MEMBER_ID)] \
73+
)
74+
75+
typedef enum {
76+
_Py_HASHLIB_MD_FAMILY(MD) = 0,
77+
_Py_HASHLIB_MD_FAMILY(SHA1),
78+
_Py_HASHLIB_MD_FAMILY(SHA2),
79+
_Py_HASHLIB_MD_FAMILY(SHA2t),
80+
_Py_HASHLIB_MD_FAMILY(SHA3),
81+
_Py_HASHLIB_MD_FAMILY(SHA3_XOF),
82+
_Py_HASHLIB_MD_FAMILY(BLAKE2),
83+
} _Py_HASHLIB_MD_NAMESPACE(family);
84+
85+
typedef enum {
86+
/* MD-family */
87+
_Py_HASHLIB_MD_MEMBER(md5) = 0,
88+
/* SHA-1 family */
89+
_Py_HASHLIB_MD_MEMBER(sha1),
90+
/* SHA-2 family */
91+
_Py_HASHLIB_MD_MEMBER(sha224),
92+
_Py_HASHLIB_MD_MEMBER(sha256),
93+
_Py_HASHLIB_MD_MEMBER(sha384),
94+
_Py_HASHLIB_MD_MEMBER(sha512),
95+
/* Truncated SHA-2 family */
96+
_Py_HASHLIB_MD_MEMBER(sha512_224),
97+
_Py_HASHLIB_MD_MEMBER(sha512_256),
98+
/* SHA-3 family */
99+
_Py_HASHLIB_MD_MEMBER(sha3_224),
100+
_Py_HASHLIB_MD_MEMBER(sha3_256),
101+
_Py_HASHLIB_MD_MEMBER(sha3_384),
102+
_Py_HASHLIB_MD_MEMBER(sha3_512),
103+
/* SHA-3 XOF SHAKE family */
104+
_Py_HASHLIB_MD_MEMBER(shake_128),
105+
_Py_HASHLIB_MD_MEMBER(shake_256),
106+
/* BLAKE-2 family */
107+
_Py_HASHLIB_MD_MEMBER(blake2b),
108+
_Py_HASHLIB_MD_MEMBER(blake2s),
109+
} _Py_HASHLIB_MD_NAMESPACE(member);
110+
111+
static const char *_Py_HASHLIB_MD_NAMES[] = {
112+
#define DECL_MESSAGE_DIGEST_NAME(ID) [_Py_HASHLIB_MD_MEMBER(ID)] = #ID
113+
/* MD-family */
114+
DECL_MESSAGE_DIGEST_NAME(md5),
115+
/* SHA-1 family */
116+
DECL_MESSAGE_DIGEST_NAME(sha1),
117+
/* SHA-2 family */
118+
DECL_MESSAGE_DIGEST_NAME(sha224),
119+
DECL_MESSAGE_DIGEST_NAME(sha256),
120+
DECL_MESSAGE_DIGEST_NAME(sha384),
121+
DECL_MESSAGE_DIGEST_NAME(sha512),
122+
/* Truncated SHA-2 family */
123+
DECL_MESSAGE_DIGEST_NAME(sha512_224),
124+
DECL_MESSAGE_DIGEST_NAME(sha512_256),
125+
/* SHA-3 family */
126+
DECL_MESSAGE_DIGEST_NAME(sha3_224),
127+
DECL_MESSAGE_DIGEST_NAME(sha3_256),
128+
DECL_MESSAGE_DIGEST_NAME(sha3_384),
129+
DECL_MESSAGE_DIGEST_NAME(sha3_512),
130+
/* SHA-3 XOF SHAKE family */
131+
DECL_MESSAGE_DIGEST_NAME(shake_128),
132+
DECL_MESSAGE_DIGEST_NAME(shake_256),
133+
/* BLAKE-2 family */
134+
DECL_MESSAGE_DIGEST_NAME(blake2b),
135+
DECL_MESSAGE_DIGEST_NAME(blake2s),
136+
#undef DECL_MESSAGE_DIGEST_NAME
137+
NULL /* sentinel */
138+
};
139+
140+
#endif // !_HASHLIB_HASHLIB_FETCH_H
Lines changed: 8 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,14 @@
1-
/* Common code for use by all hashlib related modules. */
1+
#ifndef _HASHLIB_HASHLIB_MUTEX_H
2+
#define _HASHLIB_HASHLIB_MUTEX_H
23

3-
#include "pycore_lock.h" // PyMutex
4+
#include "Python.h"
5+
#include "pycore_lock.h" // PyMutex
46

57
/*
6-
* Internal error messages used for reporting an unsupported hash algorithm.
7-
* The algorithm can be given by its name, a callable or a PEP-247 module.
8-
* The same message is raised by Lib/hashlib.py::__get_builtin_constructor()
9-
* and _hmacmodule.c::find_hash_info().
10-
*/
11-
#define HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S"
12-
#define HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s"
13-
14-
/*
15-
* Given a PyObject* obj, fill in the Py_buffer* viewp with the result
16-
* of PyObject_GetBuffer. Sets an exception and issues the erraction
17-
* on any errors, e.g. 'return NULL' or 'goto error'.
8+
* Message length above which the GIL is to be released
9+
* when performing hashing operations.
1810
*/
19-
#define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \
20-
if (PyUnicode_Check((obj))) { \
21-
PyErr_SetString(PyExc_TypeError, \
22-
"Strings must be encoded before hashing");\
23-
erraction; \
24-
} \
25-
if (!PyObject_CheckBuffer((obj))) { \
26-
PyErr_SetString(PyExc_TypeError, \
27-
"object supporting the buffer API required"); \
28-
erraction; \
29-
} \
30-
if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
31-
erraction; \
32-
} \
33-
if ((viewp)->ndim > 1) { \
34-
PyErr_SetString(PyExc_BufferError, \
35-
"Buffer must be single dimension"); \
36-
PyBuffer_Release((viewp)); \
37-
erraction; \
38-
} \
39-
} while(0)
40-
41-
#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \
42-
GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL)
11+
#define HASHLIB_GIL_MINSIZE 2048
4312

4413
/*
4514
* Helper code to synchronize access to the hash object when the GIL is
@@ -64,12 +33,6 @@
6433
#define HASHLIB_ACQUIRE_LOCK(OBJ) PyMutex_Lock(&(OBJ)->mutex)
6534
#define HASHLIB_RELEASE_LOCK(OBJ) PyMutex_Unlock(&(OBJ)->mutex)
6635

67-
/*
68-
* Message length above which the GIL is to be released
69-
* when performing hashing operations.
70-
*/
71-
#define HASHLIB_GIL_MINSIZE 2048
72-
7336
// Macros for executing code while conditionally holding the GIL.
7437
//
7538
// These only drop the GIL if the lock acquisition itself is likely to
@@ -116,41 +79,4 @@
11679
} \
11780
} while (0)
11881

119-
static inline int
120-
_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string)
121-
{
122-
if (data != NULL && string == NULL) {
123-
// called as H(data) or H(data=...)
124-
*res = data;
125-
return 1;
126-
}
127-
else if (data == NULL && string != NULL) {
128-
// called as H(string=...)
129-
if (PyErr_WarnEx(PyExc_DeprecationWarning,
130-
"the 'string' keyword parameter is deprecated since "
131-
"Python 3.15 and slated for removal in Python 3.19; "
132-
"use the 'data' keyword parameter or pass the data "
133-
"to hash as a positional argument instead", 1) < 0)
134-
{
135-
*res = NULL;
136-
return -1;
137-
}
138-
*res = string;
139-
return 1;
140-
}
141-
else if (data == NULL && string == NULL) {
142-
// fast path when no data is given
143-
assert(!PyErr_Occurred());
144-
*res = NULL;
145-
return 0;
146-
}
147-
else {
148-
// called as H(data=..., string)
149-
*res = NULL;
150-
PyErr_SetString(PyExc_TypeError,
151-
"'data' and 'string' are mutually exclusive "
152-
"and support for 'string' keyword parameter "
153-
"is slated for removal in a future version.");
154-
return -1;
155-
}
156-
}
82+
#endif // !_HASHLIB_HASHLIB_MUTEX_H

0 commit comments

Comments
 (0)