Bug 1873140 - Avoid using invalid enum values during EnumSet iteration; r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D197824
This commit is contained in:
Jan Varga 2024-02-02 09:43:10 +00:00
Родитель ee30d0fa58
Коммит 9cb0b76439
1 изменённых файлов: 21 добавлений и 10 удалений

Просмотреть файл

@ -182,9 +182,7 @@ class EnumSet {
/** /**
* Test is an element is contained in the set. * Test is an element is contained in the set.
*/ */
bool contains(T aEnum) const { bool contains(T aEnum) const { return HasBitFor(aEnum); }
return static_cast<bool>(mBitField & BitFor(aEnum));
}
/** /**
* Test if a set is contained in the set. * Test if a set is contained in the set.
@ -241,7 +239,7 @@ class EnumSet {
mVersion = mSet->mVersion; mVersion = mSet->mVersion;
#endif #endif
MOZ_ASSERT(aPos <= kMaxBits); MOZ_ASSERT(aPos <= kMaxBits);
if (aPos != kMaxBits && !mSet->contains(T(mPos))) { if (aPos != kMaxBits && !mSet->HasBitAt(mPos)) {
++*this; ++*this;
} }
} }
@ -278,7 +276,7 @@ class EnumSet {
T operator*() const { T operator*() const {
MOZ_ASSERT(mSet); MOZ_ASSERT(mSet);
MOZ_ASSERT(mPos < kMaxBits); MOZ_ASSERT(mPos < kMaxBits);
MOZ_ASSERT(mSet->contains(T(mPos))); MOZ_ASSERT(mSet->HasBitAt(mPos));
checkVersion(); checkVersion();
return T(mPos); return T(mPos);
} }
@ -289,7 +287,7 @@ class EnumSet {
checkVersion(); checkVersion();
do { do {
mPos++; mPos++;
} while (mPos < kMaxBits && !mSet->contains(T(mPos))); } while (mPos < kMaxBits && !mSet->HasBitAt(mPos));
return *this; return *this;
} }
}; };
@ -300,17 +298,30 @@ class EnumSet {
private: private:
constexpr static Serialized BitFor(T aEnum) { constexpr static Serialized BitFor(T aEnum) {
auto bitNumber = static_cast<size_t>(aEnum); const auto pos = static_cast<size_t>(aEnum);
MOZ_DIAGNOSTIC_ASSERT(bitNumber < kMaxBits); return BitAt(pos);
}
constexpr static Serialized BitAt(size_t aPos) {
MOZ_DIAGNOSTIC_ASSERT(aPos < kMaxBits);
if constexpr (std::is_unsigned_v<Serialized>) { if constexpr (std::is_unsigned_v<Serialized>) {
return static_cast<Serialized>(Serialized{1} << bitNumber); return static_cast<Serialized>(Serialized{1} << aPos);
} else { } else {
Serialized bitField; Serialized bitField;
bitField[bitNumber] = true; bitField[aPos] = true;
return bitField; return bitField;
} }
} }
constexpr bool HasBitFor(T aEnum) const {
const auto pos = static_cast<size_t>(aEnum);
return HasBitAt(pos);
}
constexpr bool HasBitAt(size_t aPos) const {
return static_cast<bool>(mBitField & BitAt(aPos));
}
constexpr void IncVersion() { constexpr void IncVersion() {
#ifdef DEBUG #ifdef DEBUG
mVersion++; mVersion++;