From f1d36d8efaecd5c84cb35e35119b283f37d83c40 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 31 Jul 2018 09:50:16 +0300 Subject: bpo-33729: Fix issues with arguments parsing in hashlib. (GH-8346) * help(hashlib) didn't work because of incorrect module name in blake2b and blake2s classes. * Constructors blake2*(), sha3_*(), shake_*() and keccak_*() incorrectly accepted keyword argument "string" for binary data, but documented as accepting the "data" keyword argument. Now this parameter is positional-only. * Keyword-only parameters in blake2b() and blake2s() were not documented as keyword-only. * Default value for some parameters of blake2b() and blake2s() was None, which is not acceptable value. * The length argument for shake_*.digest() was wrapped out to 32 bits. * The argument for shake_128.digest() and shake_128.hexdigest() was not positional-only as intended. * TypeError messages for incorrect arguments in all constructors sha3_*(), shake_*() and keccak_*() incorrectly referred to sha3_224. Also made the following enhancements: * More accurately specified input and result types for strings, bytes and bytes-like objects. * Unified positional parameter names for update() and constructors. * Improved formatting. --- Doc/library/hashlib.rst | 27 ++++---- Lib/hashlib.py | 29 ++++----- Lib/test/test_hashlib.py | 6 +- .../2018-07-20-09-11-05.bpo-33729.sO6iTb.rst | 1 + Modules/_blake2/blake2b_impl.c | 61 +++++++++--------- Modules/_blake2/blake2s_impl.c | 61 +++++++++--------- Modules/_blake2/clinic/blake2b_impl.c.h | 59 +++++++++--------- Modules/_blake2/clinic/blake2s_impl.c.h | 59 +++++++++--------- Modules/_hashopenssl.c | 8 ++- Modules/_sha3/clinic/sha3module.c.h | 59 ++++-------------- Modules/_sha3/sha3module.c | 72 ++++++++++++---------- Modules/clinic/_hashopenssl.c.h | 4 +- 12 files changed, 214 insertions(+), 232 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-07-20-09-11-05.bpo-33729.sO6iTb.rst diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index da941e5..baf6b0a 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -101,7 +101,7 @@ More condensed: .. function:: new(name[, data]) - Is a generic constructor that takes the string name of the desired + Is a generic constructor that takes the string *name* of the desired algorithm as its first parameter. It also exists to allow access to the above listed hashes as well as any other algorithms that your OpenSSL library may offer. The named constructors are much faster than :func:`new` @@ -162,10 +162,10 @@ A hash object has the following attributes: A hash object has the following methods: -.. method:: hash.update(arg) +.. method:: hash.update(data) - Update the hash object with the object *arg*, which must be interpretable as - a buffer of bytes. Repeated calls are equivalent to a single call with the + Update the hash object with the :term:`bytes-like object`. + Repeated calls are equivalent to a single call with the concatenation of all the arguments: ``m.update(a); m.update(b)`` is equivalent to ``m.update(a+b)``. @@ -206,7 +206,7 @@ by the SHAKE algorithm. .. method:: shake.digest(length) Return the digest of the data passed to the :meth:`update` method so far. - This is a bytes object of size ``length`` which may contain bytes in + This is a bytes object of size *length* which may contain bytes in the whole range from 0 to 255. @@ -262,9 +262,10 @@ include a `salt `_. The function provides scrypt password-based key derivation function as defined in :rfc:`7914`. - *password* and *salt* must be bytes-like objects. Applications and - libraries should limit *password* to a sensible length (e.g. 1024). *salt* - should be about 16 or more bytes from a proper source, e.g. :func:`os.urandom`. + *password* and *salt* must be :term:`bytes-like objects + `. Applications and libraries should limit *password* + to a sensible length (e.g. 1024). *salt* should be about 16 or more + bytes from a proper source, e.g. :func:`os.urandom`. *n* is the CPU/Memory cost factor, *r* the block size, *p* parallelization factor and *maxmem* limits memory (OpenSSL 1.1.0 defaults to 32 MiB). @@ -305,11 +306,11 @@ Creating hash objects New hash objects are created by calling constructor functions: -.. function:: blake2b(data=b'', digest_size=64, key=b'', salt=b'', \ +.. function:: blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', \ person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \ node_depth=0, inner_size=0, last_node=False) -.. function:: blake2s(data=b'', digest_size=32, key=b'', salt=b'', \ +.. function:: blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', \ person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \ node_depth=0, inner_size=0, last_node=False) @@ -317,8 +318,8 @@ New hash objects are created by calling constructor functions: These functions return the corresponding hash objects for calculating BLAKE2b or BLAKE2s. They optionally take these general parameters: -* *data*: initial chunk of data to hash, which must be interpretable as buffer - of bytes. +* *data*: initial chunk of data to hash, which must be + :term:`bytes-like object`. It can be passed only as positional argument. * *digest_size*: size of output digest in bytes. @@ -427,7 +428,7 @@ object, and, finally, get the digest out of the object by calling As a shortcut, you can pass the first chunk of data to update directly to the -constructor as the first argument (or as *data* keyword argument): +constructor as the positional argument: >>> from hashlib import blake2b >>> blake2b(b'Hello world').hexdigest() diff --git a/Lib/hashlib.py b/Lib/hashlib.py index e30c610..4e783a8 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -25,18 +25,18 @@ Choose your hash function wisely. Some have known collision weaknesses. sha384 and sha512 will be slow on 32 bit platforms. Hash objects have these methods: - - update(arg): Update the hash object with the bytes in arg. Repeated calls - are equivalent to a single call with the concatenation of all - the arguments. - - digest(): Return the digest of the bytes passed to the update() method - so far. - - hexdigest(): Like digest() except the digest is returned as a unicode - object of double length, containing only hexadecimal digits. - - copy(): Return a copy (clone) of the hash object. This can be used to - efficiently compute the digests of strings that share a common - initial substring. - -For example, to obtain the digest of the string 'Nobody inspects the + - update(data): Update the hash object with the bytes in data. Repeated calls + are equivalent to a single call with the concatenation of all + the arguments. + - digest(): Return the digest of the bytes passed to the update() method + so far as a bytes object. + - hexdigest(): Like digest() except the digest is returned as a string + of double length, containing only hexadecimal digits. + - copy(): Return a copy (clone) of the hash object. This can be used to + efficiently compute the digests of datas that share a common + initial substring. + +For example, to obtain the digest of the byte string 'Nobody inspects the spammish repetition': >>> import hashlib @@ -130,14 +130,15 @@ def __get_openssl_constructor(name): def __py_new(name, data=b'', **kwargs): """new(name, data=b'', **kwargs) - Return a new hashing object using the - named algorithm; optionally initialized with data (which must be bytes). + named algorithm; optionally initialized with data (which must be + a bytes-like object). """ return __get_builtin_constructor(name)(data, **kwargs) def __hash_new(name, data=b'', **kwargs): """new(name, data=b'') - Return a new hashing object using the named algorithm; - optionally initialized with data (which must be bytes). + optionally initialized with data (which must be a bytes-like object). """ if name in {'blake2b', 'blake2s'}: # Prefer our blake2 implementation. diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 0f76b24..c8a873f 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -568,8 +568,12 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(ValueError, constructor, node_offset=-1) self.assertRaises(OverflowError, constructor, node_offset=max_offset+1) + self.assertRaises(TypeError, constructor, data=b'') + self.assertRaises(TypeError, constructor, string=b'') + self.assertRaises(TypeError, constructor, '') + constructor( - string=b'', + b'', key=b'', salt=b'', person=b'', diff --git a/Misc/NEWS.d/next/Library/2018-07-20-09-11-05.bpo-33729.sO6iTb.rst b/Misc/NEWS.d/next/Library/2018-07-20-09-11-05.bpo-33729.sO6iTb.rst new file mode 100644 index 0000000..c471872 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-07-20-09-11-05.bpo-33729.sO6iTb.rst @@ -0,0 +1 @@ +Fixed issues with arguments parsing in :mod:`hashlib`. diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c index 92d7c5c..7ad4b65 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -47,10 +47,10 @@ typedef struct { #include "clinic/blake2b_impl.c.h" /*[clinic input] -module _blake2b -class _blake2b.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType" +module _blake2 +class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6893358c6622aecf]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/ static BLAKE2bObject * @@ -66,13 +66,14 @@ new_BLAKE2bObject(PyTypeObject *type) /*[clinic input] @classmethod -_blake2b.blake2b.__new__ as py_blake2b_new - string as data: object = NULL +_blake2.blake2b.__new__ as py_blake2b_new + data: object(c_default="NULL") = b'' + / * - digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2b.blake2b.MAX_DIGEST_SIZE - key: Py_buffer = None - salt: Py_buffer = None - person: Py_buffer = None + digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2.blake2b.MAX_DIGEST_SIZE + key: Py_buffer(c_default="NULL", py_default="b''") = None + salt: Py_buffer(c_default="NULL", py_default="b''") = None + person: Py_buffer(c_default="NULL", py_default="b''") = None fanout: int = 1 depth: int = 1 leaf_size: unsigned_long = 0 @@ -90,7 +91,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, int fanout, int depth, unsigned long leaf_size, unsigned long long node_offset, int node_depth, int inner_size, int last_node) -/*[clinic end generated code: output=65e732c66c2297a0 input=75ab5196b695adee]*/ +/*[clinic end generated code: output=65e732c66c2297a0 input=82be35a4e6a9daa2]*/ { BLAKE2bObject *self = NULL; Py_buffer buf; @@ -237,14 +238,14 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, } /*[clinic input] -_blake2b.blake2b.copy +_blake2.blake2b.copy Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -_blake2b_blake2b_copy_impl(BLAKE2bObject *self) -/*[clinic end generated code: output=c89cd33550ab1543 input=4c9c319f18f10747]*/ +_blake2_blake2b_copy_impl(BLAKE2bObject *self) +/*[clinic end generated code: output=ff6acee5f93656ae input=e383c2d199fd8a2e]*/ { BLAKE2bObject *cpy; @@ -259,21 +260,21 @@ _blake2b_blake2b_copy_impl(BLAKE2bObject *self) } /*[clinic input] -_blake2b.blake2b.update +_blake2.blake2b.update - obj: object + data: object / -Update this hash object's state with the provided string. +Update this hash object's state with the provided bytes-like object. [clinic start generated code]*/ static PyObject * -_blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj) -/*[clinic end generated code: output=a888f07c4cddbe94 input=3ecb8c13ee4260f2]*/ +_blake2_blake2b_update(BLAKE2bObject *self, PyObject *data) +/*[clinic end generated code: output=010dfcbe22654359 input=ffc4aa6a6a225d31]*/ { Py_buffer buf; - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); + GET_BUFFER_VIEW_OR_ERROUT(data, &buf); if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) self->lock = PyThread_allocate_lock(); @@ -293,14 +294,14 @@ _blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj) } /*[clinic input] -_blake2b.blake2b.digest +_blake2.blake2b.digest -Return the digest value as a string of binary data. +Return the digest value as a bytes object. [clinic start generated code]*/ static PyObject * -_blake2b_blake2b_digest_impl(BLAKE2bObject *self) -/*[clinic end generated code: output=b13a79360d984740 input=ac2fa462ebb1b9c7]*/ +_blake2_blake2b_digest_impl(BLAKE2bObject *self) +/*[clinic end generated code: output=a5864660f4bfc61a input=7d21659e9c5fff02]*/ { uint8_t digest[BLAKE2B_OUTBYTES]; blake2b_state state_cpy; @@ -314,14 +315,14 @@ _blake2b_blake2b_digest_impl(BLAKE2bObject *self) } /*[clinic input] -_blake2b.blake2b.hexdigest +_blake2.blake2b.hexdigest Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ static PyObject * -_blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self) -/*[clinic end generated code: output=6a503611715b24bd input=d58f0b2f37812e33]*/ +_blake2_blake2b_hexdigest_impl(BLAKE2bObject *self) +/*[clinic end generated code: output=b5598a87d8794a60 input=76930f6946351f56]*/ { uint8_t digest[BLAKE2B_OUTBYTES]; blake2b_state state_cpy; @@ -335,10 +336,10 @@ _blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self) static PyMethodDef py_blake2b_methods[] = { - _BLAKE2B_BLAKE2B_COPY_METHODDEF - _BLAKE2B_BLAKE2B_DIGEST_METHODDEF - _BLAKE2B_BLAKE2B_HEXDIGEST_METHODDEF - _BLAKE2B_BLAKE2B_UPDATE_METHODDEF + _BLAKE2_BLAKE2B_COPY_METHODDEF + _BLAKE2_BLAKE2B_DIGEST_METHODDEF + _BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF + _BLAKE2_BLAKE2B_UPDATE_METHODDEF {NULL, NULL} }; diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c index 8c49082..8864fd8 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -47,10 +47,10 @@ typedef struct { #include "clinic/blake2s_impl.c.h" /*[clinic input] -module _blake2s -class _blake2s.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType" +module _blake2 +class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=edbfcf7557a685a7]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/ static BLAKE2sObject * @@ -66,13 +66,14 @@ new_BLAKE2sObject(PyTypeObject *type) /*[clinic input] @classmethod -_blake2s.blake2s.__new__ as py_blake2s_new - string as data: object = NULL +_blake2.blake2s.__new__ as py_blake2s_new + data: object(c_default="NULL") = b'' + / * - digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2s.blake2s.MAX_DIGEST_SIZE - key: Py_buffer = None - salt: Py_buffer = None - person: Py_buffer = None + digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2.blake2s.MAX_DIGEST_SIZE + key: Py_buffer(c_default="NULL", py_default="b''") = None + salt: Py_buffer(c_default="NULL", py_default="b''") = None + person: Py_buffer(c_default="NULL", py_default="b''") = None fanout: int = 1 depth: int = 1 leaf_size: unsigned_long = 0 @@ -90,7 +91,7 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, int fanout, int depth, unsigned long leaf_size, unsigned long long node_offset, int node_depth, int inner_size, int last_node) -/*[clinic end generated code: output=b95806be0514dcf7 input=f18d6efd9b9a1271]*/ +/*[clinic end generated code: output=b95806be0514dcf7 input=641c0509debf714d]*/ { BLAKE2sObject *self = NULL; Py_buffer buf; @@ -237,14 +238,14 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, } /*[clinic input] -_blake2s.blake2s.copy +_blake2.blake2s.copy Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -_blake2s_blake2s_copy_impl(BLAKE2sObject *self) -/*[clinic end generated code: output=6c5bada404b7aed7 input=c8858e887ae4a07a]*/ +_blake2_blake2s_copy_impl(BLAKE2sObject *self) +/*[clinic end generated code: output=5b90131c4eae275e input=0b9d44942f0fe4b2]*/ { BLAKE2sObject *cpy; @@ -259,21 +260,21 @@ _blake2s_blake2s_copy_impl(BLAKE2sObject *self) } /*[clinic input] -_blake2s.blake2s.update +_blake2.blake2s.update - obj: object + data: object / -Update this hash object's state with the provided string. +Update this hash object's state with the provided bytes-like object. [clinic start generated code]*/ static PyObject * -_blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj) -/*[clinic end generated code: output=fe8438a1d3cede87 input=47a408b9a3cc05c5]*/ +_blake2_blake2s_update(BLAKE2sObject *self, PyObject *data) +/*[clinic end generated code: output=757dc087fec37815 input=97500db2f9de4aaa]*/ { Py_buffer buf; - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); + GET_BUFFER_VIEW_OR_ERROUT(data, &buf); if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) self->lock = PyThread_allocate_lock(); @@ -293,14 +294,14 @@ _blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj) } /*[clinic input] -_blake2s.blake2s.digest +_blake2.blake2s.digest -Return the digest value as a string of binary data. +Return the digest value as a bytes object. [clinic start generated code]*/ static PyObject * -_blake2s_blake2s_digest_impl(BLAKE2sObject *self) -/*[clinic end generated code: output=80e81a48c6f79cf9 input=feb9a220135bdeba]*/ +_blake2_blake2s_digest_impl(BLAKE2sObject *self) +/*[clinic end generated code: output=40c566ca4bc6bc51 input=f41e0b8d6d937454]*/ { uint8_t digest[BLAKE2S_OUTBYTES]; blake2s_state state_cpy; @@ -314,14 +315,14 @@ _blake2s_blake2s_digest_impl(BLAKE2sObject *self) } /*[clinic input] -_blake2s.blake2s.hexdigest +_blake2.blake2s.hexdigest Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ static PyObject * -_blake2s_blake2s_hexdigest_impl(BLAKE2sObject *self) -/*[clinic end generated code: output=db6c5028c0a3c2e5 input=4e4877b8bd7aea91]*/ +_blake2_blake2s_hexdigest_impl(BLAKE2sObject *self) +/*[clinic end generated code: output=15153eb5e59c52eb input=c77a1321567e8952]*/ { uint8_t digest[BLAKE2S_OUTBYTES]; blake2s_state state_cpy; @@ -335,10 +336,10 @@ _blake2s_blake2s_hexdigest_impl(BLAKE2sObject *self) static PyMethodDef py_blake2s_methods[] = { - _BLAKE2S_BLAKE2S_COPY_METHODDEF - _BLAKE2S_BLAKE2S_DIGEST_METHODDEF - _BLAKE2S_BLAKE2S_HEXDIGEST_METHODDEF - _BLAKE2S_BLAKE2S_UPDATE_METHODDEF + _BLAKE2_BLAKE2S_COPY_METHODDEF + _BLAKE2_BLAKE2S_DIGEST_METHODDEF + _BLAKE2_BLAKE2S_HEXDIGEST_METHODDEF + _BLAKE2_BLAKE2S_UPDATE_METHODDEF {NULL, NULL} }; diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h index 3cb70fb..3315bf9 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -3,10 +3,9 @@ preserve [clinic start generated code]*/ PyDoc_STRVAR(py_blake2b_new__doc__, -"blake2b(string=None, *, digest_size=_blake2b.blake2b.MAX_DIGEST_SIZE,\n" -" key=None, salt=None, person=None, fanout=1, depth=1,\n" -" leaf_size=0, node_offset=0, node_depth=0, inner_size=0,\n" -" last_node=False)\n" +"blake2b(data=b\'\', /, *, digest_size=_blake2.blake2b.MAX_DIGEST_SIZE,\n" +" key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n" +" node_offset=0, node_depth=0, inner_size=0, last_node=False)\n" "--\n" "\n" "Return a new BLAKE2b hash object."); @@ -22,7 +21,7 @@ static PyObject * py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"string", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; + static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; static _PyArg_Parser _parser = {"|O$iy*y*y*iiO&O&iip:blake2b", _keywords, 0}; PyObject *data = NULL; int digest_size = BLAKE2B_OUTBYTES; @@ -60,66 +59,66 @@ exit: return return_value; } -PyDoc_STRVAR(_blake2b_blake2b_copy__doc__, +PyDoc_STRVAR(_blake2_blake2b_copy__doc__, "copy($self, /)\n" "--\n" "\n" "Return a copy of the hash object."); -#define _BLAKE2B_BLAKE2B_COPY_METHODDEF \ - {"copy", (PyCFunction)_blake2b_blake2b_copy, METH_NOARGS, _blake2b_blake2b_copy__doc__}, +#define _BLAKE2_BLAKE2B_COPY_METHODDEF \ + {"copy", (PyCFunction)_blake2_blake2b_copy, METH_NOARGS, _blake2_blake2b_copy__doc__}, static PyObject * -_blake2b_blake2b_copy_impl(BLAKE2bObject *self); +_blake2_blake2b_copy_impl(BLAKE2bObject *self); static PyObject * -_blake2b_blake2b_copy(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2b_copy(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2b_blake2b_copy_impl(self); + return _blake2_blake2b_copy_impl(self); } -PyDoc_STRVAR(_blake2b_blake2b_update__doc__, -"update($self, obj, /)\n" +PyDoc_STRVAR(_blake2_blake2b_update__doc__, +"update($self, data, /)\n" "--\n" "\n" -"Update this hash object\'s state with the provided string."); +"Update this hash object\'s state with the provided bytes-like object."); -#define _BLAKE2B_BLAKE2B_UPDATE_METHODDEF \ - {"update", (PyCFunction)_blake2b_blake2b_update, METH_O, _blake2b_blake2b_update__doc__}, +#define _BLAKE2_BLAKE2B_UPDATE_METHODDEF \ + {"update", (PyCFunction)_blake2_blake2b_update, METH_O, _blake2_blake2b_update__doc__}, -PyDoc_STRVAR(_blake2b_blake2b_digest__doc__, +PyDoc_STRVAR(_blake2_blake2b_digest__doc__, "digest($self, /)\n" "--\n" "\n" -"Return the digest value as a string of binary data."); +"Return the digest value as a bytes object."); -#define _BLAKE2B_BLAKE2B_DIGEST_METHODDEF \ - {"digest", (PyCFunction)_blake2b_blake2b_digest, METH_NOARGS, _blake2b_blake2b_digest__doc__}, +#define _BLAKE2_BLAKE2B_DIGEST_METHODDEF \ + {"digest", (PyCFunction)_blake2_blake2b_digest, METH_NOARGS, _blake2_blake2b_digest__doc__}, static PyObject * -_blake2b_blake2b_digest_impl(BLAKE2bObject *self); +_blake2_blake2b_digest_impl(BLAKE2bObject *self); static PyObject * -_blake2b_blake2b_digest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2b_digest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2b_blake2b_digest_impl(self); + return _blake2_blake2b_digest_impl(self); } -PyDoc_STRVAR(_blake2b_blake2b_hexdigest__doc__, +PyDoc_STRVAR(_blake2_blake2b_hexdigest__doc__, "hexdigest($self, /)\n" "--\n" "\n" "Return the digest value as a string of hexadecimal digits."); -#define _BLAKE2B_BLAKE2B_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)_blake2b_blake2b_hexdigest, METH_NOARGS, _blake2b_blake2b_hexdigest__doc__}, +#define _BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF \ + {"hexdigest", (PyCFunction)_blake2_blake2b_hexdigest, METH_NOARGS, _blake2_blake2b_hexdigest__doc__}, static PyObject * -_blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self); +_blake2_blake2b_hexdigest_impl(BLAKE2bObject *self); static PyObject * -_blake2b_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2b_blake2b_hexdigest_impl(self); + return _blake2_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=afc5c45dff0a24f9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=39c77de2142faa12 input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h index b444f7b..23d19ec 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -3,10 +3,9 @@ preserve [clinic start generated code]*/ PyDoc_STRVAR(py_blake2s_new__doc__, -"blake2s(string=None, *, digest_size=_blake2s.blake2s.MAX_DIGEST_SIZE,\n" -" key=None, salt=None, person=None, fanout=1, depth=1,\n" -" leaf_size=0, node_offset=0, node_depth=0, inner_size=0,\n" -" last_node=False)\n" +"blake2s(data=b\'\', /, *, digest_size=_blake2.blake2s.MAX_DIGEST_SIZE,\n" +" key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n" +" node_offset=0, node_depth=0, inner_size=0, last_node=False)\n" "--\n" "\n" "Return a new BLAKE2s hash object."); @@ -22,7 +21,7 @@ static PyObject * py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"string", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; + static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; static _PyArg_Parser _parser = {"|O$iy*y*y*iiO&O&iip:blake2s", _keywords, 0}; PyObject *data = NULL; int digest_size = BLAKE2S_OUTBYTES; @@ -60,66 +59,66 @@ exit: return return_value; } -PyDoc_STRVAR(_blake2s_blake2s_copy__doc__, +PyDoc_STRVAR(_blake2_blake2s_copy__doc__, "copy($self, /)\n" "--\n" "\n" "Return a copy of the hash object."); -#define _BLAKE2S_BLAKE2S_COPY_METHODDEF \ - {"copy", (PyCFunction)_blake2s_blake2s_copy, METH_NOARGS, _blake2s_blake2s_copy__doc__}, +#define _BLAKE2_BLAKE2S_COPY_METHODDEF \ + {"copy", (PyCFunction)_blake2_blake2s_copy, METH_NOARGS, _blake2_blake2s_copy__doc__}, static PyObject * -_blake2s_blake2s_copy_impl(BLAKE2sObject *self); +_blake2_blake2s_copy_impl(BLAKE2sObject *self); static PyObject * -_blake2s_blake2s_copy(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2s_copy(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2s_blake2s_copy_impl(self); + return _blake2_blake2s_copy_impl(self); } -PyDoc_STRVAR(_blake2s_blake2s_update__doc__, -"update($self, obj, /)\n" +PyDoc_STRVAR(_blake2_blake2s_update__doc__, +"update($self, data, /)\n" "--\n" "\n" -"Update this hash object\'s state with the provided string."); +"Update this hash object\'s state with the provided bytes-like object."); -#define _BLAKE2S_BLAKE2S_UPDATE_METHODDEF \ - {"update", (PyCFunction)_blake2s_blake2s_update, METH_O, _blake2s_blake2s_update__doc__}, +#define _BLAKE2_BLAKE2S_UPDATE_METHODDEF \ + {"update", (PyCFunction)_blake2_blake2s_update, METH_O, _blake2_blake2s_update__doc__}, -PyDoc_STRVAR(_blake2s_blake2s_digest__doc__, +PyDoc_STRVAR(_blake2_blake2s_digest__doc__, "digest($self, /)\n" "--\n" "\n" -"Return the digest value as a string of binary data."); +"Return the digest value as a bytes object."); -#define _BLAKE2S_BLAKE2S_DIGEST_METHODDEF \ - {"digest", (PyCFunction)_blake2s_blake2s_digest, METH_NOARGS, _blake2s_blake2s_digest__doc__}, +#define _BLAKE2_BLAKE2S_DIGEST_METHODDEF \ + {"digest", (PyCFunction)_blake2_blake2s_digest, METH_NOARGS, _blake2_blake2s_digest__doc__}, static PyObject * -_blake2s_blake2s_digest_impl(BLAKE2sObject *self); +_blake2_blake2s_digest_impl(BLAKE2sObject *self); static PyObject * -_blake2s_blake2s_digest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2s_digest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2s_blake2s_digest_impl(self); + return _blake2_blake2s_digest_impl(self); } -PyDoc_STRVAR(_blake2s_blake2s_hexdigest__doc__, +PyDoc_STRVAR(_blake2_blake2s_hexdigest__doc__, "hexdigest($self, /)\n" "--\n" "\n" "Return the digest value as a string of hexadecimal digits."); -#define _BLAKE2S_BLAKE2S_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)_blake2s_blake2s_hexdigest, METH_NOARGS, _blake2s_blake2s_hexdigest__doc__}, +#define _BLAKE2_BLAKE2S_HEXDIGEST_METHODDEF \ + {"hexdigest", (PyCFunction)_blake2_blake2s_hexdigest, METH_NOARGS, _blake2_blake2s_hexdigest__doc__}, static PyObject * -_blake2s_blake2s_hexdigest_impl(BLAKE2sObject *self); +_blake2_blake2s_hexdigest_impl(BLAKE2sObject *self); static PyObject * -_blake2s_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) +_blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { - return _blake2s_blake2s_hexdigest_impl(self); + return _blake2_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=b705723d16f21f57 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a31a1d56f0e0781f input=a9049054013a1b77]*/ diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index b6dcc06..40cd632 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -729,6 +729,10 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) #if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER) #define PY_SCRYPT 1 +/* XXX: Parameters salt, n, r and p should be required keyword-only parameters. + They are optional in the Argument Clinic declaration only due to a + limitation of PyArg_ParseTupleAndKeywords. */ + /*[clinic input] _hashlib.scrypt @@ -858,13 +862,13 @@ _hashlib.hmac_digest msg: Py_buffer digest: str -Single-shot HMAC +Single-shot HMAC. [clinic start generated code]*/ static PyObject * _hashlib_hmac_digest_impl(PyObject *module, Py_buffer *key, Py_buffer *msg, const char *digest) -/*[clinic end generated code: output=75630e684cdd8762 input=10e964917921e2f2]*/ +/*[clinic end generated code: output=75630e684cdd8762 input=562d2f4249511bd3]*/ { unsigned char md[EVP_MAX_MD_SIZE] = {0}; unsigned int md_len = 0; diff --git a/Modules/_sha3/clinic/sha3module.c.h b/Modules/_sha3/clinic/sha3module.c.h index a1e80b0..b2a896e 100644 --- a/Modules/_sha3/clinic/sha3module.c.h +++ b/Modules/_sha3/clinic/sha3module.c.h @@ -2,33 +2,6 @@ preserve [clinic start generated code]*/ -PyDoc_STRVAR(py_sha3_new__doc__, -"sha3_224(string=None)\n" -"--\n" -"\n" -"Return a new SHA3 hash object with a hashbit length of 28 bytes."); - -static PyObject * -py_sha3_new_impl(PyTypeObject *type, PyObject *data); - -static PyObject * -py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"string", NULL}; - static _PyArg_Parser _parser = {"|O:sha3_224", _keywords, 0}; - PyObject *data = NULL; - - if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, - &data)) { - goto exit; - } - return_value = py_sha3_new_impl(type, data); - -exit: - return return_value; -} - PyDoc_STRVAR(_sha3_sha3_224_copy__doc__, "copy($self, /)\n" "--\n" @@ -51,7 +24,7 @@ PyDoc_STRVAR(_sha3_sha3_224_digest__doc__, "digest($self, /)\n" "--\n" "\n" -"Return the digest value as a string of binary data."); +"Return the digest value as a bytes object."); #define _SHA3_SHA3_224_DIGEST_METHODDEF \ {"digest", (PyCFunction)_sha3_sha3_224_digest, METH_NOARGS, _sha3_sha3_224_digest__doc__}, @@ -84,36 +57,33 @@ _sha3_sha3_224_hexdigest(SHA3object *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_sha3_sha3_224_update__doc__, -"update($self, obj, /)\n" +"update($self, data, /)\n" "--\n" "\n" -"Update this hash object\'s state with the provided string."); +"Update this hash object\'s state with the provided bytes-like object."); #define _SHA3_SHA3_224_UPDATE_METHODDEF \ {"update", (PyCFunction)_sha3_sha3_224_update, METH_O, _sha3_sha3_224_update__doc__}, PyDoc_STRVAR(_sha3_shake_128_digest__doc__, -"digest($self, /, length)\n" +"digest($self, length, /)\n" "--\n" "\n" -"Return the digest value as a string of binary data."); +"Return the digest value as a bytes object."); #define _SHA3_SHAKE_128_DIGEST_METHODDEF \ - {"digest", (PyCFunction)_sha3_shake_128_digest, METH_FASTCALL|METH_KEYWORDS, _sha3_shake_128_digest__doc__}, + {"digest", (PyCFunction)_sha3_shake_128_digest, METH_O, _sha3_shake_128_digest__doc__}, static PyObject * _sha3_shake_128_digest_impl(SHA3object *self, unsigned long length); static PyObject * -_sha3_shake_128_digest(SHA3object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sha3_shake_128_digest(SHA3object *self, PyObject *arg) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"length", NULL}; - static _PyArg_Parser _parser = {"k:digest", _keywords, 0}; unsigned long length; - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &length)) { + if (!PyArg_Parse(arg, "O&:digest", _PyLong_UnsignedLong_Converter, &length)) { goto exit; } return_value = _sha3_shake_128_digest_impl(self, length); @@ -123,27 +93,24 @@ exit: } PyDoc_STRVAR(_sha3_shake_128_hexdigest__doc__, -"hexdigest($self, /, length)\n" +"hexdigest($self, length, /)\n" "--\n" "\n" "Return the digest value as a string of hexadecimal digits."); #define _SHA3_SHAKE_128_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)_sha3_shake_128_hexdigest, METH_FASTCALL|METH_KEYWORDS, _sha3_shake_128_hexdigest__doc__}, + {"hexdigest", (PyCFunction)_sha3_shake_128_hexdigest, METH_O, _sha3_shake_128_hexdigest__doc__}, static PyObject * _sha3_shake_128_hexdigest_impl(SHA3object *self, unsigned long length); static PyObject * -_sha3_shake_128_hexdigest(SHA3object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sha3_shake_128_hexdigest(SHA3object *self, PyObject *arg) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"length", NULL}; - static _PyArg_Parser _parser = {"k:hexdigest", _keywords, 0}; unsigned long length; - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &length)) { + if (!PyArg_Parse(arg, "O&:hexdigest", _PyLong_UnsignedLong_Converter, &length)) { goto exit; } return_value = _sha3_shake_128_hexdigest_impl(self, length); @@ -151,4 +118,4 @@ _sha3_shake_128_hexdigest(SHA3object *self, PyObject *const *args, Py_ssize_t na exit: return return_value; } -/*[clinic end generated code: output=a3aeb6c3b2fbd905 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bf823532a7bffe68 input=a9049054013a1b77]*/ diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index 970ce16..f5032fc 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -170,21 +170,20 @@ newSHA3object(PyTypeObject *type) } -/*[clinic input] -@classmethod -_sha3.sha3_224.__new__ as py_sha3_new - string as data: object = NULL - -Return a new SHA3 hash object with a hashbit length of 28 bytes. -[clinic start generated code]*/ - static PyObject * -py_sha3_new_impl(PyTypeObject *type, PyObject *data) -/*[clinic end generated code: output=8d5c34279e69bf09 input=d7c582b950a858b6]*/ +py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { SHA3object *self = NULL; Py_buffer buf = {NULL, NULL}; HashReturn res; + PyObject *data = NULL; + + if (!_PyArg_NoKeywords(_PyType_Name(type), kwargs)) { + return NULL; + } + if (!PyArg_UnpackTuple(args, _PyType_Name(type), 0, 1, &data)) { + return NULL; + } self = newSHA3object(type); if (self == NULL) { @@ -292,12 +291,12 @@ _sha3_sha3_224_copy_impl(SHA3object *self) /*[clinic input] _sha3.sha3_224.digest -Return the digest value as a string of binary data. +Return the digest value as a bytes object. [clinic start generated code]*/ static PyObject * _sha3_sha3_224_digest_impl(SHA3object *self) -/*[clinic end generated code: output=fd531842e20b2d5b input=a5807917d219b30e]*/ +/*[clinic end generated code: output=fd531842e20b2d5b input=5b2a659536bbd248]*/ { unsigned char digest[SHA3_MAX_DIGESTSIZE + SHA3_LANESIZE]; SHA3_state temp; @@ -347,20 +346,20 @@ _sha3_sha3_224_hexdigest_impl(SHA3object *self) /*[clinic input] _sha3.sha3_224.update - obj: object + data: object / -Update this hash object's state with the provided string. +Update this hash object's state with the provided bytes-like object. [clinic start generated code]*/ static PyObject * -_sha3_sha3_224_update(SHA3object *self, PyObject *obj) -/*[clinic end generated code: output=06721d55b483e0af input=be44bf0d1c279791]*/ +_sha3_sha3_224_update(SHA3object *self, PyObject *data) +/*[clinic end generated code: output=d3223352286ed357 input=a887f54dcc4ae227]*/ { Py_buffer buf; HashReturn res; - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); + GET_BUFFER_VIEW_OR_ERROUT(data, &buf); /* add new data, the function takes the length in bits not bytes */ if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { @@ -529,44 +528,49 @@ static PyGetSetDef SHA3_getseters[] = { py_sha3_new, /* tp_new */ \ } +PyDoc_STRVAR(sha3_224__doc__, +"sha3_224([data]) -> SHA3 object\n\ +\n\ +Return a new SHA3 hash object with a hashbit length of 28 bytes."); + PyDoc_STRVAR(sha3_256__doc__, -"sha3_256([string]) -> SHA3 object\n\ +"sha3_256([data]) -> SHA3 object\n\ \n\ Return a new SHA3 hash object with a hashbit length of 32 bytes."); PyDoc_STRVAR(sha3_384__doc__, -"sha3_384([string]) -> SHA3 object\n\ +"sha3_384([data]) -> SHA3 object\n\ \n\ Return a new SHA3 hash object with a hashbit length of 48 bytes."); PyDoc_STRVAR(sha3_512__doc__, -"sha3_512([string]) -> SHA3 object\n\ +"sha3_512([data]) -> SHA3 object\n\ \n\ Return a new SHA3 hash object with a hashbit length of 64 bytes."); -SHA3_TYPE(SHA3_224type, "_sha3.sha3_224", py_sha3_new__doc__, SHA3_methods); +SHA3_TYPE(SHA3_224type, "_sha3.sha3_224", sha3_224__doc__, SHA3_methods); SHA3_TYPE(SHA3_256type, "_sha3.sha3_256", sha3_256__doc__, SHA3_methods); SHA3_TYPE(SHA3_384type, "_sha3.sha3_384", sha3_384__doc__, SHA3_methods); SHA3_TYPE(SHA3_512type, "_sha3.sha3_512", sha3_512__doc__, SHA3_methods); #ifdef PY_WITH_KECCAK PyDoc_STRVAR(keccak_224__doc__, -"keccak_224([string]) -> Keccak object\n\ +"keccak_224([data]) -> Keccak object\n\ \n\ Return a new Keccak hash object with a hashbit length of 28 bytes."); PyDoc_STRVAR(keccak_256__doc__, -"keccak_256([string]) -> Keccak object\n\ +"keccak_256([data]) -> Keccak object\n\ \n\ Return a new Keccak hash object with a hashbit length of 32 bytes."); PyDoc_STRVAR(keccak_384__doc__, -"keccak_384([string]) -> Keccak object\n\ +"keccak_384([data]) -> Keccak object\n\ \n\ Return a new Keccak hash object with a hashbit length of 48 bytes."); PyDoc_STRVAR(keccak_512__doc__, -"keccak_512([string]) -> Keccak object\n\ +"keccak_512([data]) -> Keccak object\n\ \n\ Return a new Keccak hash object with a hashbit length of 64 bytes."); @@ -624,15 +628,15 @@ _SHAKE_digest(SHA3object *self, unsigned long digestlen, int hex) /*[clinic input] _sha3.shake_128.digest - length: unsigned_long(bitwise=True) - \ + length: unsigned_long + / -Return the digest value as a string of binary data. +Return the digest value as a bytes object. [clinic start generated code]*/ static PyObject * _sha3_shake_128_digest_impl(SHA3object *self, unsigned long length) -/*[clinic end generated code: output=2313605e2f87bb8f input=608c8ca80ae9d115]*/ +/*[clinic end generated code: output=2313605e2f87bb8f input=418ef6a36d2e6082]*/ { return _SHAKE_digest(self, length, 0); } @@ -641,15 +645,15 @@ _sha3_shake_128_digest_impl(SHA3object *self, unsigned long length) /*[clinic input] _sha3.shake_128.hexdigest - length: unsigned_long(bitwise=True) - \ + length: unsigned_long + / Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ static PyObject * _sha3_shake_128_hexdigest_impl(SHA3object *self, unsigned long length) -/*[clinic end generated code: output=bf8e2f1e490944a8 input=64e56b4760db4573]*/ +/*[clinic end generated code: output=bf8e2f1e490944a8 input=69fb29b0926ae321]*/ { return _SHAKE_digest(self, length, 1); } @@ -664,12 +668,12 @@ static PyMethodDef SHAKE_methods[] = { }; PyDoc_STRVAR(shake_128__doc__, -"shake_128([string]) -> SHAKE object\n\ +"shake_128([data]) -> SHAKE object\n\ \n\ Return a new SHAKE hash object."); PyDoc_STRVAR(shake_256__doc__, -"shake_256([string]) -> SHAKE object\n\ +"shake_256([data]) -> SHAKE object\n\ \n\ Return a new SHAKE hash object."); diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index cbc8638..070f829 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -58,7 +58,7 @@ PyDoc_STRVAR(_hashlib_hmac_digest__doc__, "hmac_digest($module, /, key, msg, digest)\n" "--\n" "\n" -"Single-shot HMAC"); +"Single-shot HMAC."); #define _HASHLIB_HMAC_DIGEST_METHODDEF \ {"hmac_digest", (PyCFunction)_hashlib_hmac_digest, METH_FASTCALL|METH_KEYWORDS, _hashlib_hmac_digest__doc__}, @@ -99,4 +99,4 @@ exit: #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=b5b90821caf05391 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b129f1a6ec7b8503 input=a9049054013a1b77]*/ -- cgit v0.12