From 113cf3ab98cc779a236460dcc5c65c50b6f65f6c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 31 Mar 2026 19:54:53 +0300 Subject: [PATCH 1/2] gh-147944: Increase range of bytes_per_sep Accepted range for the bytes_per_sep argument of bytes.hex(), bytearray.hex(), memoryview.hex(), and binascii.b2a_hex() is now increased, so passing sys.maxsize and -sys.maxsize is now valid. --- Include/internal/pycore_strhex.h | 28 ++++++------- Lib/test/test_bytes.py | 4 +- Lib/test/test_memoryview.py | 4 +- ...-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst | 4 ++ Modules/binascii.c | 10 ++--- Modules/clinic/binascii.c.h | 39 +++++++++++++------ Objects/bytearrayobject.c | 7 ++-- Objects/bytesobject.c | 6 +-- Objects/clinic/bytearrayobject.c.h | 21 +++++++--- Objects/clinic/bytesobject.c.h | 20 +++++++--- Objects/clinic/memoryobject.c.h | 21 +++++++--- Objects/memoryobject.c | 6 +-- Python/pystrhex.c | 23 +++++------ 13 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst diff --git a/Include/internal/pycore_strhex.h b/Include/internal/pycore_strhex.h index 225f423912f2c2..656acae960ac0d 100644 --- a/Include/internal/pycore_strhex.h +++ b/Include/internal/pycore_strhex.h @@ -10,28 +10,24 @@ extern "C" { // Returns a str() containing the hex representation of argbuf. // Export for '_hashlib' shared extension. -PyAPI_FUNC(PyObject*) _Py_strhex(const - char* argbuf, - const Py_ssize_t arglen); +PyAPI_FUNC(PyObject *) _Py_strhex(const char *argbuf, Py_ssize_t arglen); // Returns a bytes() containing the ASCII hex representation of argbuf. -extern PyObject* _Py_strhex_bytes( - const char* argbuf, - const Py_ssize_t arglen); +extern PyObject *_Py_strhex_bytes(const char *argbuf, Py_ssize_t arglen); // These variants include support for a separator between every N bytes: -extern PyObject* _Py_strhex_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +extern PyObject *_Py_strhex_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); // Export for 'binascii' shared extension -PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +PyAPI_FUNC(PyObject *) _Py_strhex_bytes_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); #ifdef __cplusplus } diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index df22d5cd96ee0c..2a9f0297569df8 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -551,10 +551,10 @@ def test_hex_separator_basics(self): self.assertEqual(three_bytes.hex('*', -2), 'b901*ef') self.assertEqual(three_bytes.hex(sep=':', bytes_per_sep=2), 'b9:01ef') self.assertEqual(three_bytes.hex(sep='*', bytes_per_sep=-2), 'b901*ef') - for bytes_per_sep in 3, -3, 2**31-1, -(2**31-1): + for bytes_per_sep in 3, -3, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 6e9f916f77b346..22b9f6af758f88 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -718,10 +718,10 @@ def test_memoryview_hex_separator(self): self.assertEqual(m2.hex(':', -2), '6564:6362:61') self.assertEqual(m2.hex(sep=':', bytes_per_sep=2), '65:6463:6261') self.assertEqual(m2.hex(sep=':', bytes_per_sep=-2), '6564:6362:61') - for bytes_per_sep in 5, -5, 2**31-1, -(2**31-1): + for bytes_per_sep in 5, -5, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') diff --git a/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst b/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst new file mode 100644 index 00000000000000..7ba75bac79c0ee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst @@ -0,0 +1,4 @@ +Accepted range for the *bytes_per_sep* argument of :meth:`bytes.hex`, +:meth:`bytearray.hex`, :meth:`memoryview.hex`, and :func:`binascii.b2a_hex` +is now increased, so passing ``sys.maxsize`` and ``-sys.maxsize`` is now +valid. diff --git a/Modules/binascii.c b/Modules/binascii.c index c51bb9c3c77371..658148d554bf17 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -2010,7 +2010,7 @@ binascii.b2a_hex data: Py_buffer sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2030,8 +2030,8 @@ b'b9_01ef' static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=a26937946a81d2c7 input=ec0ade6ba2e43543]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=7d703f866f74a813 input=6a1606f01a87118c]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); @@ -2048,8 +2048,8 @@ available as "b2a_hex()". static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=d12aa1b001b15199 input=bc317bd4e241f76b]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=b99b3b39d234a3d4 input=bc317bd4e241f76b]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 7a411bfc829943..34d2707a517c9f 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_long.h" // _PyLong_Size_t_Converter() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() @@ -1007,7 +1008,7 @@ PyDoc_STRVAR(binascii_b2a_hex__doc__, static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1044,7 +1045,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1063,9 +1064,17 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_b2a_hex_impl(module, &data, sep, bytes_per_sep); @@ -1099,7 +1108,7 @@ PyDoc_STRVAR(binascii_hexlify__doc__, static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1136,7 +1145,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1155,9 +1164,17 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_hexlify_impl(module, &data, sep, bytes_per_sep); @@ -1411,4 +1428,4 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -/*[clinic end generated code: output=242c0c56b918bd33 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6b6cb98a6bc95f62 input=a9049054013a1b77]*/ diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index e2fea94e099626..ae800197035b61 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2641,7 +2641,7 @@ bytearray.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2660,8 +2660,9 @@ Create a string of hexadecimal numbers from a bytearray object. [clinic start generated code]*/ static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=29c4e5ef72c565a0 input=7784107de7048873]*/ +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9563921aff1262b input=d2b23ef057cfcad5]*/ { char* argbuf = PyByteArray_AS_STRING(self); Py_ssize_t arglen = PyByteArray_GET_SIZE(self); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 00c1c63b8e01c6..db9fc557c91b21 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2744,7 +2744,7 @@ bytes.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2763,8 +2763,8 @@ Create a string of hexadecimal numbers from a bytes object. [clinic start generated code]*/ static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=1f134da504064139 input=1a21282b1f1ae595]*/ +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=588821f02cb9d8f5 input=bd8eceb755d8230f]*/ { const char *argbuf = PyBytes_AS_STRING(self); Py_ssize_t arglen = PyBytes_GET_SIZE(self); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index cf60d0ceadc7d1..a85e20a68cbda9 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -1692,7 +1692,8 @@ PyDoc_STRVAR(bytearray_hex__doc__, {"hex", _PyCFunction_CAST(bytearray_hex), METH_FASTCALL|METH_KEYWORDS, bytearray_hex__doc__}, static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep); +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep); static PyObject * bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1728,7 +1729,7 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1744,9 +1745,17 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: Py_BEGIN_CRITICAL_SECTION(self); @@ -1835,4 +1844,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=2d76ef023928424f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d8452c9a0ab61e91 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 00cf13d422d900..43492ace5c891d 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -1254,7 +1254,7 @@ PyDoc_STRVAR(bytes_hex__doc__, {"hex", _PyCFunction_CAST(bytes_hex), METH_FASTCALL|METH_KEYWORDS, bytes_hex__doc__}, static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep); +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep); static PyObject * bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1290,7 +1290,7 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1306,9 +1306,17 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = bytes_hex_impl((PyBytesObject *)self, sep, bytes_per_sep); @@ -1411,4 +1419,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=08b9507244f73638 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=accadabe56cdabb9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h index 28cfd1a22080c9..d97c626532c803 100644 --- a/Objects/clinic/memoryobject.c.h +++ b/Objects/clinic/memoryobject.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(memoryview__doc__, @@ -366,7 +367,7 @@ PyDoc_STRVAR(memoryview_hex__doc__, static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -402,7 +403,7 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -418,9 +419,17 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = memoryview_hex_impl((PyMemoryViewObject *)self, sep, bytes_per_sep); @@ -496,4 +505,4 @@ memoryview_index(PyObject *self, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=154f4c04263ccb24 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=348b6ddb98a1f412 input=a9049054013a1b77]*/ diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index bca77851ac2961..4cbbb7eb7cd0fd 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2358,7 +2358,7 @@ memoryview.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2378,8 +2378,8 @@ Return the data in the buffer as a str of hexadecimal numbers. static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9bb00c7a8e86056 input=dc48a56ed3b058ae]*/ { Py_buffer *src = VIEW_ADDR(self); diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 698e7f26fbaae7..14d5719313afd2 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -111,9 +111,10 @@ _Py_hexlify_simd(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) #endif /* HAVE_EFFICIENT_BUILTIN_SHUFFLEVECTOR */ -static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, int bytes_per_sep_group, - const int return_bytes) +static PyObject * +_Py_strhex_impl(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_sep_group, + int return_bytes) { assert(arglen >= 0); @@ -149,7 +150,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, else { bytes_per_sep_group = 0; } - unsigned int abs_bytes_per_sep = _Py_ABS_CAST(unsigned int, bytes_per_sep_group); + size_t abs_bytes_per_sep = _Py_ABS_CAST(size_t, bytes_per_sep_group); Py_ssize_t resultlen = 0; if (bytes_per_sep_group && arglen > 0) { /* How many sep characters we'll be inserting. */ @@ -203,7 +204,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, /* The number of complete chunk+sep periods */ Py_ssize_t chunks = (arglen - 1) / abs_bytes_per_sep; Py_ssize_t chunk; - unsigned int k; + size_t k; if (bytes_per_sep_group < 0) { i = j = 0; @@ -251,30 +252,30 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, return retval; } -PyObject * _Py_strhex(const char* argbuf, const Py_ssize_t arglen) +PyObject * _Py_strhex(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) +PyObject* _Py_strhex_bytes(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 1); } /* These variants include support for a separator between every N bytes: */ -PyObject* _Py_strhex_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 1); } From c6735a87785bdaccbf6b16ac071c44ce2b8f9622 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 1 Apr 2026 10:58:06 +0300 Subject: [PATCH 2/2] Get rid of some special cases in tests for base64.b16encode(). --- Lib/test/test_base64.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index bb3b3c1e2353c4..d5f8f44e280b54 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -216,11 +216,9 @@ def _common_test_wrapcol(self, func, data): eq(func(data, wrapcol=80), expected) eq(func(b'', wrapcol=0), func(b'')) eq(func(b'', wrapcol=1), func(b'')) - if func is not base64.b16encode: - eq(func(data, wrapcol=sys.maxsize), expected) + eq(func(data, wrapcol=sys.maxsize), expected) if check_impl_detail(): - if func is not base64.b16encode: - eq(func(data, wrapcol=sys.maxsize*2), expected) + eq(func(data, wrapcol=sys.maxsize*2), expected) with self.assertRaises(OverflowError): func(data, wrapcol=2**1000) with self.assertRaises(ValueError):