]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-124248: Fix crash in struct when processing 0p fields (GH-124251) (#124278)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 20 Sep 2024 10:29:43 +0000 (12:29 +0200)
committerGitHub <noreply@github.com>
Fri, 20 Sep 2024 10:29:43 +0000 (10:29 +0000)
gh-124248: Fix crash in struct when processing 0p fields (GH-124251)
(cherry picked from commit 63f196090f90cbfe5f698824655f74dea5cb2b29)

Co-authored-by: Brian Schubert <brianm.schubert@gmail.com>
Lib/test/test_struct.py
Misc/ACKS
Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst [new file with mode: 0644]
Modules/_struct.c

index 8d4b13a618315f8436c9643c5f54d226e438fd74..39ca78cece1fb0692dca2ce0a640354e4c995635 100644 (file)
@@ -96,6 +96,13 @@ class StructTest(unittest.TestCase):
             ('10s', b'helloworld', b'helloworld', b'helloworld', 0),
             ('11s', b'helloworld', b'helloworld\0', b'helloworld\0', 1),
             ('20s', b'helloworld', b'helloworld'+10*b'\0', b'helloworld'+10*b'\0', 1),
+            ('0p', b'helloworld', b'', b'', 1),
+            ('1p', b'helloworld', b'\x00', b'\x00', 1),
+            ('2p', b'helloworld', b'\x01h', b'\x01h', 1),
+            ('10p', b'helloworld', b'\x09helloworl', b'\x09helloworl', 1),
+            ('11p', b'helloworld', b'\x0Ahelloworld', b'\x0Ahelloworld', 0),
+            ('12p', b'helloworld', b'\x0Ahelloworld\0', b'\x0Ahelloworld\0', 1),
+            ('20p', b'helloworld', b'\x0Ahelloworld'+9*b'\0', b'\x0Ahelloworld'+9*b'\0', 1),
             ('b', 7, b'\7', b'\7', 0),
             ('b', -7, b'\371', b'\371', 0),
             ('B', 7, b'\7', b'\7', 0),
@@ -339,6 +346,7 @@ class StructTest(unittest.TestCase):
     def test_p_code(self):
         # Test p ("Pascal string") code.
         for code, input, expected, expectedback in [
+                ('0p', b'abc', b'',                b''),
                 ('p',  b'abc', b'\x00',            b''),
                 ('1p', b'abc', b'\x00',            b''),
                 ('2p', b'abc', b'\x01a',           b'a'),
@@ -580,6 +588,7 @@ class StructTest(unittest.TestCase):
         self.check_sizeof('187s', 1)
         self.check_sizeof('20p', 1)
         self.check_sizeof('0s', 1)
+        self.check_sizeof('0p', 1)
         self.check_sizeof('0c', 0)
 
     def test_boundary_error_message(self):
index 15d4470e2842cf38ca2259fa26603265db5e3def..b5dc32ee507689f72d4d3a2f32b609b2bbc33bbc 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1637,6 +1637,7 @@ Scott Schram
 Robin Schreiber
 Chad J. Schroeder
 Simon-Martin Schroeder
+Brian Schubert
 Christian Schubert
 Sam Schulenburg
 Andreas Schwab
diff --git a/Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst b/Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst
new file mode 100644 (file)
index 0000000..1bd333f
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed potential crash when using :mod:`struct` to process zero-width
+'Pascal string' fields (``0p``).
index e8d9f86e1901ac443d77cb0a9d85d670d74ba12f..84474043b01b28d42e1ba65eb58749568875d872 100644 (file)
@@ -1662,9 +1662,16 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom,
             if (e->format == 's') {
                 v = PyBytes_FromStringAndSize(res, code->size);
             } else if (e->format == 'p') {
-                Py_ssize_t n = *(unsigned char*)res;
-                if (n >= code->size)
-                    n = code->size - 1;
+                Py_ssize_t n;
+                if (code->size == 0) {
+                    n = 0;
+                }
+                else {
+                    n = *(unsigned char*)res;
+                    if (n >= code->size) {
+                        n = code->size - 1;
+                    }
+                }
                 v = PyBytes_FromStringAndSize(res + 1, n);
             } else {
                 v = e->unpack(state, res, e);
@@ -1975,8 +1982,12 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset,
                     n = PyByteArray_GET_SIZE(v);
                     p = PyByteArray_AS_STRING(v);
                 }
-                if (n > (code->size - 1))
+                if (code->size == 0) {
+                    n = 0;
+                }
+                else if (n > (code->size - 1)) {
                     n = code->size - 1;
+                }
                 if (n > 0)
                     memcpy(res + 1, p, n);
                 if (n > 255)