Add safe_cast (RIPD-1702):

This change ensures that no overflow can occur when casting
between enums and integral types.
This commit is contained in:
Howard Hinnant
2018-12-21 17:13:58 -05:00
committed by Nik Bougalis
parent 494724578a
commit 148bbf4e8f
35 changed files with 213 additions and 86 deletions

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
#define RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
#include <ripple/basics/safe_cast.h>
#include <ripple/ledger/RawView.h>
#include <ripple/ledger/ReadView.h>
#include <boost/optional.hpp>
@@ -27,6 +28,7 @@
namespace ripple {
enum ApplyFlags
: std::uint32_t
{
tapNONE = 0x00,
@@ -48,14 +50,14 @@ ApplyFlags
operator|(ApplyFlags const& lhs,
ApplyFlags const& rhs)
{
return static_cast<ApplyFlags>(
static_cast<std::underlying_type_t<ApplyFlags>>(lhs) |
static_cast<std::underlying_type_t<ApplyFlags>>(rhs));
return safe_cast<ApplyFlags>(
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) |
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
}
static_assert((tapPREFER_QUEUE | tapRETRY) == static_cast<ApplyFlags>(0x60),
static_assert((tapPREFER_QUEUE | tapRETRY) == safe_cast<ApplyFlags>(0x60u),
"ApplyFlags operator |");
static_assert((tapRETRY | tapPREFER_QUEUE) == static_cast<ApplyFlags>(0x60),
static_assert((tapRETRY | tapPREFER_QUEUE) == safe_cast<ApplyFlags>(0x60u),
"ApplyFlags operator |");
constexpr
@@ -63,9 +65,9 @@ ApplyFlags
operator&(ApplyFlags const& lhs,
ApplyFlags const& rhs)
{
return static_cast<ApplyFlags>(
static_cast<std::underlying_type_t<ApplyFlags>>(lhs) &
static_cast<std::underlying_type_t<ApplyFlags>>(rhs));
return safe_cast<ApplyFlags>(
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) &
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
}
static_assert((tapPREFER_QUEUE & tapRETRY) == tapNONE,
@@ -77,11 +79,11 @@ constexpr
ApplyFlags
operator~(ApplyFlags const& flags)
{
return static_cast<ApplyFlags>(
~static_cast<std::underlying_type_t<ApplyFlags>>(flags));
return safe_cast<ApplyFlags>(
~safe_cast<std::underlying_type_t<ApplyFlags>>(flags));
}
static_assert(~tapRETRY == static_cast<ApplyFlags>(~0x20),
static_assert(~tapRETRY == safe_cast<ApplyFlags>(0xFFFFFFDFu),
"ApplyFlags operator ~");
inline

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_LEDGER_CASHDIFF_H_INCLUDED
#define RIPPLE_LEDGER_CASHDIFF_H_INCLUDED
#include <ripple/basics/safe_cast.h>
#include <ripple/protocol/STAmount.h>
#include <memory> // std::unique_ptr
@@ -44,13 +45,13 @@ inline CashFilter operator| (CashFilter lhs, CashFilter rhs)
{
using ul_t = std::underlying_type<CashFilter>::type;
return static_cast<CashFilter>(
static_cast<ul_t>(lhs) | static_cast<ul_t>(rhs));
safe_cast<ul_t>(lhs) | safe_cast<ul_t>(rhs));
}
inline CashFilter operator& (CashFilter lhs, CashFilter rhs)
{
using ul_t = std::underlying_type<CashFilter>::type;
return static_cast<CashFilter>(
static_cast<ul_t>(lhs) & static_cast<ul_t>(rhs));
safe_cast<ul_t>(lhs) & safe_cast<ul_t>(rhs));
}
//------------------------------------------------------------------------------