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]

Reply via email to