Skip to content

Commit 4c889e8

Browse files
fix LOAD_INDEX/STORE_INDEX to use _DK_INDICES_BASE for well-defined pointer arithmetic
The previous macros used negative indexing from the PyDictKeysObject pointer (e.g. ((int8_t*)keys)[-1-idx]) to access the indices stored before the struct. This is undefined behavior: the compiler sees keys as typed PyDictKeysObject* and negative indices are formally out-of-bounds, allowing MSVC's release optimizer to generate incorrect hash table lookups. Fix by using _DK_INDICES_BASE(keys) (the actual malloc base) with positive forward indexing, which is well-defined pointer arithmetic within the allocation.
1 parent e9d9ec5 commit 4c889e8

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

Objects/dictobject.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ ASSERT_DICT_LOCKED(PyObject *op)
182182

183183
#define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
184184
#define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
185-
#define LOAD_INDEX(keys, size, idx) _Py_atomic_load_int##size##_relaxed(&((const int##size##_t*)(keys))[-1 - (idx)]);
186-
#define STORE_INDEX(keys, size, idx, value) _Py_atomic_store_int##size##_relaxed(&((int##size##_t*)(keys))[-1 - (idx)], (int##size##_t)value);
185+
#define LOAD_INDEX(keys, size, idx) _Py_atomic_load_int##size##_relaxed(&((const int##size##_t*)(_DK_INDICES_BASE(keys)))[(idx)]);
186+
#define STORE_INDEX(keys, size, idx, value) _Py_atomic_store_int##size##_relaxed(&((int##size##_t*)(_DK_INDICES_BASE(keys)))[(idx)], (int##size##_t)value);
187187
#define ASSERT_OWNED_OR_SHARED(mp) \
188188
assert(_Py_IsOwnedByCurrentThread((PyObject *)mp) || IS_DICT_SHARED(mp));
189189

@@ -262,8 +262,8 @@ static inline void split_keys_entry_added(PyDictKeysObject *keys)
262262
#define UNLOCK_KEYS_IF_SPLIT(keys, kind)
263263
#define IS_DICT_SHARED(mp) (false)
264264
#define SET_DICT_SHARED(mp)
265-
#define LOAD_INDEX(keys, size, idx) ((const int##size##_t*)(keys))[-1 - (idx)]
266-
#define STORE_INDEX(keys, size, idx, value) ((int##size##_t*)(keys))[-1 - (idx)] = (int##size##_t)value
265+
#define LOAD_INDEX(keys, size, idx) ((const int##size##_t*)(_DK_INDICES_BASE(keys)))[(idx)]
266+
#define STORE_INDEX(keys, size, idx, value) ((int##size##_t*)(_DK_INDICES_BASE(keys)))[(idx)] = (int##size##_t)value
267267

268268
static inline void split_keys_entry_added(PyDictKeysObject *keys)
269269
{

0 commit comments

Comments
 (0)