diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 59133e24e649fa..bffbcb1a60757d 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -478,9 +478,9 @@ def _test_pack_into(self, pack_into): pack_into(writable_buf, None, test_string) with self.assertRaises(TypeError): pack_into(writable_buf, 0.0, test_string) - with self.assertRaises((IndexError, OverflowError)): + with self.assertRaises(OverflowError): pack_into(writable_buf, 2**1000, test_string) - with self.assertRaises((IndexError, OverflowError)): + with self.assertRaises(OverflowError): pack_into(writable_buf, -2**1000, test_string) def test_pack_into(self): diff --git a/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst b/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst new file mode 100644 index 00000000000000..f856a4be9fc9fe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst @@ -0,0 +1,2 @@ +:func:`struct.pack_into` now raises OverflowError instead of IndexError for +too large *offset* argument. diff --git a/Modules/_struct.c b/Modules/_struct.c index 34e931790ebb39..c0107d7c3574b4 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -2275,7 +2275,7 @@ Struct_pack_impl(PyStructObject *self, PyObject * const *values, Struct.pack_into buffer: Py_buffer(accept={rwbuffer}) - offset as offset_obj: object + offset: Py_ssize_t / *values: array @@ -2289,11 +2289,10 @@ help(struct) for more on format strings. static PyObject * Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, - PyObject *offset_obj, PyObject * const *values, + Py_ssize_t offset, PyObject * const *values, Py_ssize_t values_length) -/*[clinic end generated code: output=b0c2ef496135dad3 input=d0de9b9f138c782d]*/ +/*[clinic end generated code: output=aa9d9a93f5f8f77b input=9d842a368ee14245]*/ { - Py_ssize_t offset; _structmodulestate *state = get_struct_state_structinst(self); ENSURE_STRUCT_IS_READY(self); @@ -2304,12 +2303,6 @@ Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, return NULL; } - /* Extract the offset from the first argument */ - offset = PyNumber_AsSsize_t(offset_obj, PyExc_IndexError); - if (offset == -1 && PyErr_Occurred()) { - return NULL; - } - /* Support negative offsets. */ if (offset < 0) { /* Check that negative offset is low enough to fit data */ @@ -2546,7 +2539,7 @@ pack_into format as s_object: cache_struct buffer: Py_buffer(accept={rwbuffer}) - offset as offset_obj: object + offset: Py_ssize_t / *values: array @@ -2560,11 +2553,11 @@ strings. static PyObject * pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, - PyObject *offset_obj, PyObject * const *values, + Py_ssize_t offset, PyObject * const *values, Py_ssize_t values_length) -/*[clinic end generated code: output=148ef659a490eec3 input=3c5fe5bd3b6fd396]*/ +/*[clinic end generated code: output=e8bf7d422b2088ef input=086867c0f5d8a8e4]*/ { - return Struct_pack_into_impl(s_object, buffer, offset_obj, + return Struct_pack_into_impl(s_object, buffer, offset, values, values_length); } diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 11cd26174a3418..9c9d29748fcf28 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -267,7 +267,7 @@ PyDoc_STRVAR(Struct_pack_into__doc__, static PyObject * Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, - PyObject *offset_obj, PyObject * const *values, + Py_ssize_t offset, PyObject * const *values, Py_ssize_t values_length); static PyObject * @@ -275,7 +275,7 @@ Struct_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - PyObject *offset_obj; + Py_ssize_t offset; PyObject * const *values; Py_ssize_t values_length; @@ -286,10 +286,21 @@ Struct_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("pack_into", "argument 1", "read-write bytes-like object", args[0]); goto exit; } - offset_obj = args[1]; + { + 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; + } + offset = ival; + } values = args + 2; values_length = nargs - 2; - return_value = Struct_pack_into_impl((PyStructObject *)self, &buffer, offset_obj, values, values_length); + return_value = Struct_pack_into_impl((PyStructObject *)self, &buffer, offset, values, values_length); exit: /* Cleanup for buffer */ @@ -427,7 +438,7 @@ PyDoc_STRVAR(pack_into__doc__, static PyObject * pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, - PyObject *offset_obj, PyObject * const *values, + Py_ssize_t offset, PyObject * const *values, Py_ssize_t values_length); static PyObject * @@ -436,7 +447,7 @@ pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyObject *return_value = NULL; PyStructObject *s_object = NULL; Py_buffer buffer = {NULL, NULL}; - PyObject *offset_obj; + Py_ssize_t offset; PyObject * const *values; Py_ssize_t values_length; @@ -450,10 +461,21 @@ pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("pack_into", "argument 2", "read-write bytes-like object", args[1]); goto exit; } - offset_obj = args[2]; + { + 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; + } + offset = ival; + } values = args + 3; values_length = nargs - 3; - return_value = pack_into_impl(module, s_object, &buffer, offset_obj, values, values_length); + return_value = pack_into_impl(module, s_object, &buffer, offset, values, values_length); exit: /* Cleanup for s_object */ @@ -642,4 +664,4 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=dc4f86c77ab3b1c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=09ee4ac45b7e709b input=a9049054013a1b77]*/