Fix: Prevent out-of-bounds read in mi_ctz_generic32 and mi_clz_generic32

This patch ensures that both mi_ctz_generic32 and mi_clz_generic32 perform safe indexing into the de Bruijn lookup tables by masking the computed index with `& 31`.

On platforms where unsigned long is 64-bit, the result of the de Bruijn multiplication and shift could exceed the valid index range (0–31), leading to an out-of-bounds read.

This change applies a bitwise AND mask to the final index:
- `mi_ctz_generic32`: debruijn[(((x & -(int32_t)x) * 0x077CB531U) >> 27) & 31]
- `mi_clz_generic32`: debruijn[((x * 0x07C4ACDDU) >> 27) & 31]

This matches the fix applied in python/cpython#134070 to its integrated mimalloc copy.

Fixes: python/cpython#134070
This commit is contained in:
Vedant Ravindra Dhoke 2025-05-17 15:52:26 -04:00 committed by GitHub
parent af21001f7a
commit 7ec98efee7
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: B5690EEEBB952194

View file

@ -976,7 +976,8 @@ static inline size_t mi_ctz_generic32(uint32_t x) {
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
}; };
if (x==0) return 32; if (x==0) return 32;
return debruijn[(uint32_t)((x & -(int32_t)x) * (uint32_t)(0x077CB531U)) >> 27]; return debruijn[(((x & -(int32_t)x) * 0x077CB531U) >> 27) & 31];
} }
static inline size_t mi_clz_generic32(uint32_t x) { static inline size_t mi_clz_generic32(uint32_t x) {
@ -991,7 +992,8 @@ static inline size_t mi_clz_generic32(uint32_t x) {
x |= x >> 4; x |= x >> 4;
x |= x >> 8; x |= x >> 8;
x |= x >> 16; x |= x >> 16;
return debruijn[(uint32_t)(x * (uint32_t)(0x07C4ACDDU)) >> 27]; return debruijn[((x * 0x07C4ACDDU) >> 27) & 31];
} }
static inline size_t mi_ctz(size_t x) { static inline size_t mi_ctz(size_t x) {