aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2018-04-19 22:41:19 -0700
committerGitHub <noreply@github.com>2018-04-19 22:41:19 -0700
commit397f1b28c4a12e3b3ed59a89599eabc457412649 (patch)
tree7e95dd2ff8c41c8a84ecea8eed68215b20734ce7 /Objects/dict-common.h
parentClean up the readme text around PGO a bit. (GH-6538) (diff)
downloadcpython-397f1b28c4a12e3b3ed59a89599eabc457412649.tar.gz
cpython-397f1b28c4a12e3b3ed59a89599eabc457412649.tar.bz2
cpython-397f1b28c4a12e3b3ed59a89599eabc457412649.zip
bpo-33312: Fix clang ubsan out of bounds warnings in dict. (GH-6537)
Fix clang ubsan (undefined behavior sanitizer) warnings in dictobject.c by adjusting how the internal struct _dictkeysobject shared keys structure is declared. This remains ABI compatible. We get rid of the union at the end of the struct being used for conveinence to avoid typecasting in favor of char[] variable length array at the end of a struct. This is known to clang to be used for variable sized objects and will not cause an undefined behavior problem. Similarly, char arrays do not have strict aliasing undefined behavior when cast. PEP-007 does not currently list variable length arrays (VLAs) as allowed in our subset of C99. If this turns out to be a problem, the fix to this is to change the char `dk_indices[]` into `dk_indices[1]` and restore the three size computation subtractions this change removes: `- Py_MEMBER_SIZE(PyDictKeysObject, dk_indices)` If this works as is I'll make a separate PR to update PEP-007.
Diffstat (limited to 'Objects/dict-common.h')
-rw-r--r--Objects/dict-common.h11
1 files changed, 2 insertions, 9 deletions
diff --git a/Objects/dict-common.h b/Objects/dict-common.h
index 3e524686b44..71d6b027442 100644
--- a/Objects/dict-common.h
+++ b/Objects/dict-common.h
@@ -58,15 +58,8 @@ struct _dictkeysobject {
- 4 bytes if dk_size <= 0xffffffff (int32_t*)
- 8 bytes otherwise (int64_t*)
- Dynamically sized, 8 is minimum. */
- union {
- int8_t as_1[8];
- int16_t as_2[4];
- int32_t as_4[2];
-#if SIZEOF_VOID_P > 4
- int64_t as_8[1];
-#endif
- } dk_indices;
+ Dynamically sized, SIZEOF_VOID_P is minimum. */
+ char dk_indices[]; /* char is required to avoid strict aliasing. */
/* "PyDictKeyEntry dk_entries[dk_usable];" array follows:
see the DK_ENTRIES() macro */