From 656ba8e9d7173f9a34bf911695d042b6825182ac Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 8 Oct 2024 22:03:11 +0300 Subject: [PATCH 1/6] gh-125118: don't copy arbitrary values to _Bool in the struct module memcopy'ing arbitrary values to _Bool variable triggers undefined behaviour, e.g.: ```c /* a.c */ int main(void) { _Bool x; char y = 2; memcpy(&x, &y, 1); printf("%d\n", x != 0); return 0; } ``` ``` $ gcc-12 a.c -Wall && ./a.out 2 $ clang-15 a.c -Wall && ./a.out 0 $ gcc-12 a.c -Wall -fsanitize=undefined && ./a.out a.c:9:5: runtime error: load of value 2, which is not a valid value for type '_Bool' 0 $ clang-15 a.c -Wall -fsanitize=undefined && ./a.out a.c:9:20: runtime error: load of value 2, which is not a valid value for type '_Bool' SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior a.c:9:20 in 0 ``` Cridits to Alex Gaynor. --- Lib/test/test_struct.py | 3 +++ .../Library/2024-10-09-07-09-00.gh-issue-125118.J9rQ1S.rst | 1 + Modules/_struct.c | 4 +--- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-10-09-07-09-00.gh-issue-125118.J9rQ1S.rst diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index e3193c7863fbae..04ec3ed0837c82 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -540,6 +540,9 @@ def __bool__(self): for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: self.assertTrue(struct.unpack('>?', c)[0]) + self.assertTrue(struct.unpack(' Date: Wed, 9 Oct 2024 18:07:05 +0300 Subject: [PATCH 2/6] + adapt for sizeof(_Bool) > 1 Co-authored-by: Sam Gross --- Modules/_struct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_struct.c b/Modules/_struct.c index f76fe10804aba2..f1fa08a6796c9c 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -497,7 +497,8 @@ nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { - return PyBool_FromLong((*p) != 0); + const _Bool f = false; + return PyBool_FromLong(memcmp(p, &f, sizeof(_Bool)); } From f27953864488bacfbdd564d54a389aafde83ac15 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 9 Oct 2024 18:14:26 +0300 Subject: [PATCH 3/6] +1 --- Modules/_struct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_struct.c b/Modules/_struct.c index f1fa08a6796c9c..1936237d25ede0 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -497,8 +497,8 @@ nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { - const _Bool f = false; - return PyBool_FromLong(memcmp(p, &f, sizeof(_Bool)); + const _Bool _false = false; + return PyBool_FromLong(memcmp(p, &_false, sizeof(_Bool)); } From 53dfc10c075ac16a3fb72814376b69b5d2db3f6d Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 9 Oct 2024 18:19:01 +0300 Subject: [PATCH 4/6] sorry --- Modules/_struct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_struct.c b/Modules/_struct.c index 1936237d25ede0..7f4646bc002535 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -498,7 +498,7 @@ static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { const _Bool _false = false; - return PyBool_FromLong(memcmp(p, &_false, sizeof(_Bool)); + return PyBool_FromLong(memcmp(p, &_false, sizeof(_Bool))); } From 02976e7343b171f619fc190ef3bf2e937c19a098 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 9 Oct 2024 18:33:21 +0300 Subject: [PATCH 5/6] Update Modules/_struct.c Co-authored-by: Victor Stinner --- Modules/_struct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_struct.c b/Modules/_struct.c index 7f4646bc002535..1782a6a2e7056f 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -497,8 +497,8 @@ nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { - const _Bool _false = false; - return PyBool_FromLong(memcmp(p, &_false, sizeof(_Bool))); + const _Bool bool_false = false; + return PyBool_FromLong(memcmp(p, &bool_false, sizeof(_Bool))); } From 78291e449b2da10dc1546df632123241ed32d20f Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 9 Oct 2024 21:01:37 +0300 Subject: [PATCH 6/6] Update Modules/_struct.c Co-authored-by: Petr Viktorin --- Modules/_struct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_struct.c b/Modules/_struct.c index 1782a6a2e7056f..21582b945be23d 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -497,7 +497,7 @@ nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { - const _Bool bool_false = false; + const _Bool bool_false = 0; return PyBool_FromLong(memcmp(p, &bool_false, sizeof(_Bool))); }