diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 176f7d21d547..68caad0a2de5 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -15,6 +15,7 @@ #include "mozilla/DebugOnly.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/EnumSet.h" +#include "mozilla/EnumTypeTraits.h" #include "mozilla/Maybe.h" #include "mozilla/net/WebSocketFrame.h" #include "mozilla/TimeStamp.h" @@ -24,7 +25,9 @@ #include "mozilla/TypeTraits.h" #include "mozilla/IntegerTypeTraits.h" +#include #include +#include #include "nsExceptionHandler.h" #include "nsID.h" @@ -934,21 +937,43 @@ template struct ParamTraits> { typedef mozilla::EnumSet paramType; + typedef typename mozilla::EnumSet::serializedType serializedType; static void Write(Message* msg, const paramType& param) { + MOZ_RELEASE_ASSERT(IsLegalValue(param.serialize())); WriteParam(msg, param.serialize()); } static bool Read(const Message* msg, PickleIterator* iter, paramType* result) { - decltype(result->serialize()) tmp; + serializedType tmp; + if (ReadParam(msg, iter, &tmp)) { - result->deserialize(tmp); - return true; + if (IsLegalValue(tmp)) { + result->deserialize(tmp); + return true; + } } + return false; } + + static constexpr serializedType AllEnumBits() + { + return ~serializedType(0) >> + (std::numeric_limits::digits - (mozilla::MaxEnumValue::value + 1)); + } + + static constexpr bool IsLegalValue(const serializedType value) + { + static_assert(mozilla::MaxEnumValue::value < std::numeric_limits::digits, + "Enum max value is not in the range!"); + static_assert(std::is_unsigned::value)>::value, + "Type of MaxEnumValue::value specialization should be unsigned!"); + + return (value & AllEnumBits()) == value; + } }; template diff --git a/mfbt/EnumSet.h b/mfbt/EnumSet.h index 343705c4c1be..d8c8a2af8b25 100644 --- a/mfbt/EnumSet.h +++ b/mfbt/EnumSet.h @@ -27,6 +27,8 @@ template class EnumSet { public: + typedef uint32_t serializedType; + EnumSet() : mBitField(0) { @@ -209,12 +211,12 @@ class EnumSet return mBitField == 0; } - uint32_t serialize() const + serializedType serialize() const { return mBitField; } - void deserialize(uint32_t aValue) + void deserialize(serializedType aValue) { incVersion(); mBitField = aValue; @@ -320,7 +322,7 @@ class EnumSet } static const size_t kMaxBits = 32; - uint32_t mBitField; + serializedType mBitField; #ifdef DEBUG uint64_t mVersion = 0; diff --git a/mfbt/EnumTypeTraits.h b/mfbt/EnumTypeTraits.h index 223eaf8c096a..0783dd654b6f 100644 --- a/mfbt/EnumTypeTraits.h +++ b/mfbt/EnumTypeTraits.h @@ -65,6 +65,29 @@ struct EnumTypeFitsWithin static_assert(std::is_integral::value, "must provide an integral type"); }; +/* + * Provides information about highest enum member value. + * Each specialization of struct MaxEnumValue should define + * "static constexpr unsigned int value". + * + * example: + * + * enum ExampleEnum + * { + * CAT = 0, + * DOG, + * HAMSTER + * }; + * + * template <> + * struct MaxEnumValue + * { + * static constexpr unsigned int value = static_cast(HAMSTER); + * }; + */ +template +struct MaxEnumValue; // no need to define the primary template + } // namespace mozilla #endif /* mozilla_EnumTypeTraits_h */