]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
`_struct.c`: Fix UB from integer overflow in `prepare_s` (GH-145158)
authorStan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Tue, 24 Feb 2026 00:53:17 +0000 (00:53 +0000)
committerGitHub <noreply@github.com>
Tue, 24 Feb 2026 00:53:17 +0000 (16:53 -0800)
Avoid possible undefined behaviour from signed overflow in `struct` module

As discovered via oss-fuzz.

Lib/test/test_struct.py
Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst [new file with mode: 0644]
Modules/_struct.c

index bffbcb1a60757dfd4bd4b9404b4e6cbe20980d41..aa793a2c223de9654ba5a12d82b546d4ee43cca0 100644 (file)
@@ -552,6 +552,9 @@ class StructTest(ComplexesAreIdenticalMixin, unittest.TestCase):
         hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
         self.assertRaises(struct.error, struct.calcsize, hugecount2)
 
+        hugecount3 = '{}i{}q'.format(sys.maxsize // 4, sys.maxsize // 8)
+        self.assertRaises(struct.error, struct.calcsize, hugecount3)
+
     def test_trailing_counter(self):
         store = array.array('b', b' '*100)
 
diff --git a/Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst b/Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst
new file mode 100644 (file)
index 0000000..60a5e4a
--- /dev/null
@@ -0,0 +1,2 @@
+Avoid undefined behaviour from signed integer overflow when parsing format
+strings in the :mod:`struct` module.
index 7d2dfc591a2a58cd6fb2b3ed3c417aff98787adf..ae8a8ffb3c005a58d72635f5660a86d096312e72 100644 (file)
@@ -1678,7 +1678,15 @@ prepare_s(PyStructObject *self)
             case 's': _Py_FALLTHROUGH;
             case 'p': len++; ncodes++; break;
             case 'x': break;
-            default: len += num; if (num) ncodes++; break;
+            default:
+                if (num > PY_SSIZE_T_MAX - len) {
+                    goto overflow;
+                }
+                len += num;
+                if (num) {
+                    ncodes++;
+                }
+                break;
         }
 
         itemsize = e->size;