]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-125118: don't copy arbitrary values to _Bool in the struct module (GH-12516...
authorSergey B Kirpichev <skirpichev@gmail.com>
Thu, 10 Oct 2024 14:56:49 +0000 (17:56 +0300)
committerGitHub <noreply@github.com>
Thu, 10 Oct 2024 14:56:49 +0000 (14:56 +0000)
memcopy'ing arbitrary values to _Bool variable triggers undefined
behaviour. Avoid this.
We assume that `false` is represented by all zero bytes.

Credits to Alex Gaynor.

(cherry picked from commit 87d7315ac57250046372b0d9ae4619ba619c8c87)

Co-authored-by: Sam Gross <colesbury@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Lib/test/test_struct.py
Misc/NEWS.d/next/Library/2024-10-09-07-09-00.gh-issue-125118.J9rQ1S.rst [new file with mode: 0644]
Modules/_struct.c

index 39ca78cece1fb0692dca2ce0a640354e4c995635..c683e5dd6c47c62ea67e2c82e7f45b1975cbfac9 100644 (file)
@@ -529,6 +529,9 @@ class StructTest(unittest.TestCase):
 
         for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
             self.assertTrue(struct.unpack('>?', c)[0])
+            self.assertTrue(struct.unpack('<?', c)[0])
+            self.assertTrue(struct.unpack('=?', c)[0])
+            self.assertTrue(struct.unpack('@?', c)[0])
 
     def test_count_overflow(self):
         hugecount = '{}b'.format(sys.maxsize+1)
diff --git a/Misc/NEWS.d/next/Library/2024-10-09-07-09-00.gh-issue-125118.J9rQ1S.rst b/Misc/NEWS.d/next/Library/2024-10-09-07-09-00.gh-issue-125118.J9rQ1S.rst
new file mode 100644 (file)
index 0000000..5d57cdb
--- /dev/null
@@ -0,0 +1 @@
+Don't copy arbitrary values to :c:expr:`_Bool` in the :mod:`struct` module.
index 84474043b01b28d42e1ba65eb58749568875d872..6532174a0b172ae4e0d991e162b65d77bc4f0add 100644 (file)
@@ -483,9 +483,8 @@ nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
 static PyObject *
 nu_bool(_structmodulestate *state, const char *p, const formatdef *f)
 {
-    _Bool x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyBool_FromLong(x != 0);
+    const _Bool bool_false = 0;
+    return PyBool_FromLong(memcmp(p, &bool_false, sizeof(_Bool)));
 }