mirror of https://github.com/infosecn1nja/C3.git
Better exception safety during Read/Write
parent
16c7753e7c
commit
4a7870d0e3
|
@ -35,6 +35,9 @@ namespace FSecure
|
|||
/// @return arithmetic type.
|
||||
static T From(ByteView& bv)
|
||||
{
|
||||
if (sizeof(T) > bv.size())
|
||||
throw std::out_of_range{ OBF(": Cannot read size from ByteView ") };
|
||||
|
||||
T ret;
|
||||
memcpy(&ret, bv.data(), sizeof(T));
|
||||
bv.remove_prefix(sizeof(T));
|
||||
|
|
|
@ -167,12 +167,20 @@ namespace FSecure
|
|||
ByteVector& Concat(T const& arg, Ts const& ...args)
|
||||
{
|
||||
auto oldSize = size();
|
||||
resize(oldSize + arg.size());
|
||||
memcpy(data() + oldSize, arg.data(), arg.size());
|
||||
if constexpr (sizeof...(Ts) != 0)
|
||||
Concat(args...);
|
||||
try
|
||||
{
|
||||
resize(oldSize + arg.size());
|
||||
memcpy(data() + oldSize, arg.data(), arg.size());
|
||||
if constexpr (sizeof...(Ts) != 0)
|
||||
Concat(args...);
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
resize(oldSize);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new ByteVector with Variadic list of parameters.
|
||||
|
@ -211,7 +219,6 @@ namespace FSecure
|
|||
template<typename T, typename ...Ts, typename std::enable_if_t<std::is_same_v<decltype(FSecure::ByteConverter<T>::To(std::declval<T>())), FSecure::ByteVector >, int> = 0>
|
||||
ByteVector & Store(T const& arg, Ts const& ...args)
|
||||
{
|
||||
|
||||
Concat(FSecure::ByteConverter<T>::To(arg));
|
||||
if constexpr (sizeof...(Ts) != 0)
|
||||
Store(args...);
|
||||
|
|
|
@ -167,13 +167,22 @@ namespace FSecure
|
|||
template<typename T, typename ...Ts, typename = decltype(FSecure::ByteConverter<Utils::RemoveCVR<T>>::From(std::declval<ByteView&>()))>
|
||||
auto Read()
|
||||
{
|
||||
auto current = ByteConverter<Utils::RemoveCVR<T>>::From(*this);
|
||||
if constexpr (sizeof...(Ts) == 0)
|
||||
return current;
|
||||
else if constexpr (sizeof...(Ts) == 1)
|
||||
return std::make_tuple(std::move(current), Read<Ts...>());
|
||||
else
|
||||
return std::tuple_cat(std::make_tuple(std::move(current)), Read<Ts...>());
|
||||
auto copy = *this;
|
||||
try
|
||||
{
|
||||
auto current = ByteConverter<Utils::RemoveCVR<T>>::From(*this);
|
||||
if constexpr (sizeof...(Ts) == 0)
|
||||
return current;
|
||||
else if constexpr (sizeof...(Ts) == 1)
|
||||
return std::make_tuple(std::move(current), Read<Ts...>());
|
||||
else
|
||||
return std::tuple_cat(std::make_tuple(std::move(current)), Read<Ts...>());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
*this = copy;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -233,7 +242,7 @@ namespace FSecure
|
|||
/// @tparam Ts, rest of pointers to members.
|
||||
/// @note T is not the same as first template parameter of Create(void).
|
||||
template <typename T, typename ...Ts>
|
||||
auto Create(T, Ts...) -> decltype(typename SplitMemberPointer<T>::declaringType{std::declval<typename SplitMemberPointer<T>::type>(), std::declval<typename SplitMemberPointer<Ts>::type>()... })
|
||||
auto Create(T, Ts...) -> decltype(typename SplitMemberPointer<T>::declaringType{ std::declval<typename SplitMemberPointer<T>::type>(), std::declval<typename SplitMemberPointer<Ts>::type>()... })
|
||||
{
|
||||
return TupleToConstructor<typename SplitMemberPointer<T>::declaringType>(m_byteView.Read<typename SplitMemberPointer<T>::type, typename SplitMemberPointer<Ts>::type...>(), std::make_index_sequence<1 + sizeof...(Ts)>{});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue