Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Bug 1427229 - Perform validation when sending an EnumSet over IPC. r=…
Browse files Browse the repository at this point in the history
…botond,froydnj

MozReview-Commit-ID: Cmugi1ldc1Z
  • Loading branch information
szefoski committed Jan 21, 2018
1 parent 84dbaa7 commit 9b232f3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
31 changes: 28 additions & 3 deletions ipc/glue/IPCMessageUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -24,7 +25,9 @@
#include "mozilla/TypeTraits.h"
#include "mozilla/IntegerTypeTraits.h"

#include <limits>
#include <stdint.h>
#include <type_traits>

#include "nsExceptionHandler.h"
#include "nsID.h"
Expand Down Expand Up @@ -934,21 +937,43 @@ template<typename T>
struct ParamTraits<mozilla::EnumSet<T>>
{
typedef mozilla::EnumSet<T> paramType;
typedef typename mozilla::EnumSet<T>::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<serializedType>::digits - (mozilla::MaxEnumValue<T>::value + 1));
}

static constexpr bool IsLegalValue(const serializedType value)
{
static_assert(mozilla::MaxEnumValue<T>::value < std::numeric_limits<serializedType>::digits,
"Enum max value is not in the range!");
static_assert(std::is_unsigned<decltype(mozilla::MaxEnumValue<T>::value)>::value,
"Type of MaxEnumValue<T>::value specialization should be unsigned!");

return (value & AllEnumBits()) == value;
}
};

template<class... Ts>
Expand Down
8 changes: 5 additions & 3 deletions mfbt/EnumSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ template<typename T>
class EnumSet
{
public:
typedef uint32_t serializedType;

EnumSet()
: mBitField(0)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -320,7 +322,7 @@ class EnumSet
}

static const size_t kMaxBits = 32;
uint32_t mBitField;
serializedType mBitField;

#ifdef DEBUG
uint64_t mVersion = 0;
Expand Down
23 changes: 23 additions & 0 deletions mfbt/EnumTypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ struct EnumTypeFitsWithin
static_assert(std::is_integral<Storage>::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<ExampleEnum>
* {
* static constexpr unsigned int value = static_cast<unsigned int>(HAMSTER);
* };
*/
template <typename T>
struct MaxEnumValue; // no need to define the primary template

} // namespace mozilla

#endif /* mozilla_EnumTypeTraits_h */

0 comments on commit 9b232f3

Please sign in to comment.