diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -272,7 +272,8 @@ #endif } - uptr computeOddEvenMaskForPointerMaybe(Options Options, uptr Ptr, uptr Size) { + uptr computeOddEvenMaskForPointerMaybe(Options Options, uptr Ptr, + uptr ClassId) { if (!Options.get(OptionBit::UseOddEvenTags)) return 0; @@ -281,8 +282,7 @@ // Size to Ptr will flip the least significant set bit of Size in Ptr, so // that bit will have the pattern 010101... for consecutive blocks, which we // can use to determine which tag mask to use. - return (Ptr & (1ULL << getLeastSignificantSetBitIndex(Size))) ? 0xaaaa - : 0x5555; + return 0x5555 << ((Ptr >> SizeClassMap::getSizeLSBByClassId(ClassId)) & 1); } NOINLINE void *allocate(uptr Size, Chunk::Origin Origin, @@ -444,7 +444,7 @@ } } else { const uptr OddEvenMask = - computeOddEvenMaskForPointerMaybe(Options, BlockUptr, BlockSize); + computeOddEvenMaskForPointerMaybe(Options, BlockUptr, ClassId); TaggedPtr = prepareTaggedChunk(Ptr, Size, OddEvenMask, BlockEnd); } storePrimaryAllocationStackMaybe(Options, Ptr); @@ -1043,7 +1043,7 @@ uptr TaggedBegin, TaggedEnd; const uptr OddEvenMask = computeOddEvenMaskForPointerMaybe( Options, reinterpret_cast(getBlockBegin(Ptr, &NewHeader)), - SizeClassMap::getSizeByClassId(NewHeader.ClassId)); + NewHeader.ClassId); // Exclude the previous tag so that immediate use after free is // detected 100% of the time. setRandomTag(Ptr, Size, OddEvenMask | (1UL << PrevTag), &TaggedBegin, diff --git a/compiler-rt/lib/scudo/standalone/size_class_map.h b/compiler-rt/lib/scudo/standalone/size_class_map.h --- a/compiler-rt/lib/scudo/standalone/size_class_map.h +++ b/compiler-rt/lib/scudo/standalone/size_class_map.h @@ -85,6 +85,10 @@ return T + (T >> S) * (ClassId & M) + SizeDelta; } + static u8 getSizeLSBByClassId(uptr ClassId) { + return getLeastSignificantSetBitIndex(getSizeByClassId(ClassId)); + } + static uptr getClassIdBySize(uptr Size) { if (Size <= SizeDelta + (1 << Config::MinSizeLog)) return 1; @@ -137,7 +141,24 @@ u8 Tab[getTableSize()] = {}; }; - static constexpr SizeTable Table = {}; + static constexpr SizeTable SzTable = {}; + + struct LSBTable { + constexpr LSBTable() { + for (uptr I = 0; I != ClassesSize; ++I) { + for (u8 Bit = 0; Bit != 64; ++Bit) { + if (Config::Classes[I] & (1 << Bit)) { + Tab[I] = Bit; + break; + } + } + } + } + + u8 Tab[ClassesSize] = {}; + }; + + static constexpr LSBTable LTable = {}; public: static const u32 MaxNumCachedHint = Config::MaxNumCachedHint; @@ -152,6 +173,10 @@ return Config::Classes[ClassId - 1]; } + static u8 getSizeLSBByClassId(uptr ClassId) { + return LTable.Tab[ClassId - 1]; + } + static uptr getClassIdBySize(uptr Size) { if (Size <= Config::Classes[0]) return 1; @@ -159,7 +184,7 @@ DCHECK_LE(Size, MaxSize); if (Size <= (1 << Config::MidSizeLog)) return ((Size - 1) >> Config::MinSizeLog) + 1; - return Table.Tab[scaledLog2(Size - 1, Config::MidSizeLog, S)]; + return SzTable.Tab[scaledLog2(Size - 1, Config::MidSizeLog, S)]; } static u32 getMaxCachedHint(uptr Size) {