Ensure that switchover vars are initialized before use: (#4527)

Global variables in different TUs are initialized in an undefined order.
At least one global variable was accessing a global switchover variable.
This caused the switchover variable to be accessed in an uninitialized
state.

Since the switchover is always explicitly set before transaction
processing, this bug can not effect transaction processing, but could
effect unit tests (and potentially the value of some global variables).
Note: at the time of this patch the offending bug is not yet in
production.
This commit is contained in:
Scott Determan
2023-05-22 22:36:46 -04:00
committed by GitHub
parent 3620ac287e
commit ce997a6de8
4 changed files with 72 additions and 18 deletions

View File

@@ -186,7 +186,14 @@ mulRatio(
std::uint32_t den,
bool roundUp);
extern LocalValue<bool> stNumberSwitchover;
// Since many uses of the number class do not have access to a ledger,
// getSTNumberSwitchover needs to be globally accessible.
bool
getSTNumberSwitchover();
void
setSTNumberSwitchover(bool v);
/** RAII class to set and restore the Number switchover.
*/
@@ -198,16 +205,16 @@ class NumberSO
public:
~NumberSO()
{
*stNumberSwitchover = saved_;
setSTNumberSwitchover(saved_);
}
NumberSO(NumberSO const&) = delete;
NumberSO&
operator=(NumberSO const&) = delete;
explicit NumberSO(bool v) : saved_(*stNumberSwitchover)
explicit NumberSO(bool v) : saved_(getSTNumberSwitchover())
{
*stNumberSwitchover = v;
setSTNumberSwitchover(v);
}
};

View File

@@ -27,7 +27,28 @@
namespace ripple {
LocalValue<bool> stNumberSwitchover(true);
namespace {
// Use a static inside a function to help prevent order-of-initialzation issues
LocalValue<bool>&
getStaticSTNumberSwitchover()
{
static LocalValue<bool> r{true};
return r;
}
} // namespace
bool
getSTNumberSwitchover()
{
return *getStaticSTNumberSwitchover();
}
void
setSTNumberSwitchover(bool v)
{
*getStaticSTNumberSwitchover() = v;
}
/* The range for the mantissa when normalized */
static std::int64_t constexpr minMantissa = 1000000000000000ull;
@@ -51,7 +72,7 @@ IOUAmount::normalize()
return;
}
if (*stNumberSwitchover)
if (getSTNumberSwitchover())
{
Number const v{mantissa_, exponent_};
mantissa_ = v.mantissa();
@@ -117,7 +138,7 @@ IOUAmount::operator+=(IOUAmount const& other)
return *this;
}
if (*stNumberSwitchover)
if (getSTNumberSwitchover())
{
*this = IOUAmount{Number{*this} + Number{other}};
return *this;