https://github.com/python/cpython/commit/18347417b06d09fa7eeac68f88eb1e720e925c65
commit: 18347417b06d09fa7eeac68f88eb1e720e925c65
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-02-01T15:25:59+02:00
summary:
gh-143904: Raise OverflowError instead of IndexError for too large offset in
struct.pack_into() (GH-143905)
files:
A Misc/NEWS.d/next/Library/2026-01-16-14-02-39.gh-issue-143904.rErHHA.rst
M Lib/test/test_struct.py
M Modules/_struct.c
M Modules/clinic/_struct.c.h
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 74ae9e4c33d31f..7d2dfc591a2a58 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]*/
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]