diff --git a/include/xrpl/basics/LocalValue.h b/include/xrpl/basics/LocalValue.h index 99538a0ff2..9357b736a8 100644 --- a/include/xrpl/basics/LocalValue.h +++ b/include/xrpl/basics/LocalValue.h @@ -54,12 +54,8 @@ struct LocalValuesHolder } }; -inline LocalValuesHolder& -getLocalValuesHolder() -{ - thread_local LocalValuesHolder holder; - return holder; -} +LocalValuesHolder& +getLocalValuesHolder(); inline LocalValues*& getLocalValuesPtr() diff --git a/include/xrpl/beast/utility/Journal.h b/include/xrpl/beast/utility/Journal.h index 7eaf4a627a..6d84e41f75 100644 --- a/include/xrpl/beast/utility/Journal.h +++ b/include/xrpl/beast/utility/Journal.h @@ -139,6 +139,13 @@ public: template ScopedStream(Stream const& stream, T const& t); + /** Overload for const char* to ensure immediate copy. + This prevents stack-use-after-scope issues when the source + pointer becomes invalid before the stream buffer operations + complete (e.g., during buffer reallocation). + */ + ScopedStream(Stream const& stream, char const* t); + ScopedStream(Stream const& stream, std::ostream& manip(std::ostream&)); ScopedStream& @@ -159,6 +166,18 @@ public: std::ostream& operator<<(T const& t) const; + /** Overload for const char* to ensure immediate copy. + This prevents stack-use-after-scope issues when the source + pointer becomes invalid before the stream buffer operations + complete (e.g., during buffer reallocation). + */ + std::ostream& + operator<<(char const* t) const + { + m_ostream << std::string(t); + return m_ostream; + } + private: Sink& m_sink; Severity const m_level; @@ -239,6 +258,17 @@ public: template ScopedStream operator<<(T const& t) const; + + /** Overload for const char* to ensure immediate copy. + This prevents stack-use-after-scope issues when the source + pointer becomes invalid before the stream buffer operations + complete (e.g., during buffer reallocation). + */ + ScopedStream + operator<<(char const* t) const + { + return ScopedStream(*this, t); + } /** @} */ private: diff --git a/src/libxrpl/basics/LocalValue.cpp b/src/libxrpl/basics/LocalValue.cpp new file mode 100644 index 0000000000..47f2d8c258 --- /dev/null +++ b/src/libxrpl/basics/LocalValue.cpp @@ -0,0 +1,14 @@ +#include + +namespace xrpl { +namespace detail { + +LocalValuesHolder& +getLocalValuesHolder() +{ + thread_local LocalValuesHolder holder; + return holder; +} + +} // namespace detail +} // namespace xrpl diff --git a/src/libxrpl/beast/utility/beast_Journal.cpp b/src/libxrpl/beast/utility/beast_Journal.cpp index f9ee0cdb73..e3e309ff1c 100644 --- a/src/libxrpl/beast/utility/beast_Journal.cpp +++ b/src/libxrpl/beast/utility/beast_Journal.cpp @@ -118,6 +118,14 @@ Journal::ScopedStream::ScopedStream(Stream const& stream, std::ostream& manip(st m_ostream << manip; } +Journal::ScopedStream::ScopedStream(Stream const& stream, char const* t) : ScopedStream(stream.sink(), stream.level()) +{ + // Convert to std::string immediately to ensure the data is copied. + // This prevents stack-use-after-scope issues when the source pointer + // becomes invalid before stream buffer operations(like reallocation) complete. + m_ostream << std::string(t); +} + Journal::ScopedStream::~ScopedStream() { std::string const& s(m_ostream.str()); diff --git a/src/libxrpl/shamap/SHAMapNodeID.cpp b/src/libxrpl/shamap/SHAMapNodeID.cpp index 84150272d6..6d6811cd63 100644 --- a/src/libxrpl/shamap/SHAMapNodeID.cpp +++ b/src/libxrpl/shamap/SHAMapNodeID.cpp @@ -6,7 +6,7 @@ namespace xrpl { -static uint256 const& +static uint256 const depthMask(unsigned int depth) { enum { mask_size = 65 };