https://github.com/python/cpython/commit/d6da6803a1a20cc34795c501b7cdb6b53b6a23b6 commit: d6da6803a1a20cc34795c501b7cdb6b53b6a23b6 branch: main author: Serhiy Storchaka <storch...@gmail.com> committer: serhiy-storchaka <storch...@gmail.com> date: 2025-04-29T16:16:05+03:00 summary:
gh-132987: Support __index__() in hashlib.scrypt() (GH-133100) Even if such signature is not supported by PyArg_ParseTupleAndKeywords(), Argument Clinic supports it with inlined converters. files: M Modules/_hashopenssl.c M Modules/clinic/_hashopenssl.c.h diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 469a39cde7a2f7..48eed5eac975ed 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -1388,19 +1388,15 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name, #ifdef PY_OPENSSL_HAS_SCRYPT -/* 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 password: Py_buffer * - salt: Py_buffer = None - n as n_obj: object(subclass_of='&PyLong_Type') = None - r as r_obj: object(subclass_of='&PyLong_Type') = None - p as p_obj: object(subclass_of='&PyLong_Type') = None + salt: Py_buffer + n: unsigned_long + r: unsigned_long + p: unsigned_long maxmem: long = 0 dklen: long = 64 @@ -1410,14 +1406,13 @@ scrypt password-based key derivation function. static PyObject * _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, - PyObject *n_obj, PyObject *r_obj, PyObject *p_obj, + unsigned long n, unsigned long r, unsigned long p, long maxmem, long dklen) -/*[clinic end generated code: output=14849e2aa2b7b46c input=48a7d63bf3f75c42]*/ +/*[clinic end generated code: output=d424bc3e8c6b9654 input=0c9a84230238fd79]*/ { PyObject *key_obj = NULL; char *key; int retval; - unsigned long n, r, p; if (password->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, @@ -1425,43 +1420,18 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, return NULL; } - if (salt->buf == NULL) { - PyErr_SetString(PyExc_TypeError, - "salt is required"); - return NULL; - } if (salt->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "salt is too long."); return NULL; } - n = PyLong_AsUnsignedLong(n_obj); - if (n == (unsigned long) -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "n is required and must be an unsigned int"); - return NULL; - } if (n < 2 || n & (n - 1)) { PyErr_SetString(PyExc_ValueError, "n must be a power of 2."); return NULL; } - r = PyLong_AsUnsignedLong(r_obj); - if (r == (unsigned long) -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "r is required and must be an unsigned int"); - return NULL; - } - - p = PyLong_AsUnsignedLong(p_obj); - if (p == (unsigned long) -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "p is required and must be an unsigned int"); - return NULL; - } - if (maxmem < 0 || maxmem > INT_MAX) { /* OpenSSL 1.1.0 restricts maxmem to 32 MiB. It may change in the future. The maxmem constant is private to OpenSSL. */ diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index bfb2d9afc870a1..59ab46ca3f0978 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -7,6 +7,7 @@ preserve # include "pycore_runtime.h" // _Py_ID() #endif #include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_long.h" // _PyLong_UnsignedLong_Converter() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(EVP_copy__doc__, @@ -1381,8 +1382,7 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #if defined(PY_OPENSSL_HAS_SCRYPT) PyDoc_STRVAR(_hashlib_scrypt__doc__, -"scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n" -" maxmem=0, dklen=64)\n" +"scrypt($module, /, password, *, salt, n, r, p, maxmem=0, dklen=64)\n" "--\n" "\n" "scrypt password-based key derivation function."); @@ -1392,7 +1392,7 @@ PyDoc_STRVAR(_hashlib_scrypt__doc__, static PyObject * _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, - PyObject *n_obj, PyObject *r_obj, PyObject *p_obj, + unsigned long n, unsigned long r, unsigned long p, long maxmem, long dklen); static PyObject * @@ -1427,63 +1427,37 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[7]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 5; Py_buffer password = {NULL, NULL}; Py_buffer salt = {NULL, NULL}; - PyObject *n_obj = Py_None; - PyObject *r_obj = Py_None; - PyObject *p_obj = Py_None; + unsigned long n; + unsigned long r; + unsigned long p; long maxmem = 0; long dklen = 64; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 4, /*varpos*/ 0, argsbuf); if (!args) { goto exit; } if (PyObject_GetBuffer(args[0], &password, PyBUF_SIMPLE) != 0) { goto exit; } - if (!noptargs) { - goto skip_optional_kwonly; + if (PyObject_GetBuffer(args[1], &salt, PyBUF_SIMPLE) != 0) { + goto exit; } - if (args[1]) { - if (PyObject_GetBuffer(args[1], &salt, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } + if (!_PyLong_UnsignedLong_Converter(args[2], &n)) { + goto exit; } - if (args[2]) { - if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("scrypt", "argument 'n'", "int", args[2]); - goto exit; - } - n_obj = args[2]; - if (!--noptargs) { - goto skip_optional_kwonly; - } + if (!_PyLong_UnsignedLong_Converter(args[3], &r)) { + goto exit; } - if (args[3]) { - if (!PyLong_Check(args[3])) { - _PyArg_BadArgument("scrypt", "argument 'r'", "int", args[3]); - goto exit; - } - r_obj = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } + if (!_PyLong_UnsignedLong_Converter(args[4], &p)) { + goto exit; } - if (args[4]) { - if (!PyLong_Check(args[4])) { - _PyArg_BadArgument("scrypt", "argument 'p'", "int", args[4]); - goto exit; - } - p_obj = args[4]; - if (!--noptargs) { - goto skip_optional_kwonly; - } + if (!noptargs) { + goto skip_optional_kwonly; } if (args[5]) { maxmem = PyLong_AsLong(args[5]); @@ -1499,7 +1473,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } skip_optional_kwonly: - return_value = _hashlib_scrypt_impl(module, &password, &salt, n_obj, r_obj, p_obj, maxmem, dklen); + return_value = _hashlib_scrypt_impl(module, &password, &salt, n, r, p, maxmem, dklen); exit: /* Cleanup for password */ @@ -1897,4 +1871,4 @@ _hashlib_compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t narg #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=d908fa85e0251426 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2c78822e38be64a8 input=a9049054013a1b77]*/ _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com