diff --git a/src/pubkey.h b/src/pubkey.h index 193b4667ab..c2aa851725 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -139,7 +139,7 @@ public: template void Unserialize(Stream& s) { - unsigned int len = ::ReadCompactSize(s); + const unsigned int len(::ReadCompactSize(s)); if (len <= SIZE) { s.read((char*)vch, len); if (len != size()) { @@ -147,9 +147,7 @@ public: } } else { // invalid pubkey, skip available data - char dummy; - while (len--) - s.read(&dummy, 1); + s.ignore(len); Invalidate(); } } diff --git a/src/span.h b/src/span.h index de88fa08c5..3d96269768 100644 --- a/src/span.h +++ b/src/span.h @@ -180,6 +180,7 @@ public: return m_data[m_size - 1]; } constexpr std::size_t size() const noexcept { return m_size; } + constexpr std::size_t size_bytes() const noexcept { return sizeof(C) * m_size; } constexpr bool empty() const noexcept { return size() == 0; } CONSTEXPR_IF_NOT_DEBUG C& operator[](std::size_t pos) const noexcept { @@ -236,11 +237,35 @@ T& SpanPopBack(Span& span) return back; } +// From C++20 as_bytes and as_writeable_bytes +template +Span AsBytes(Span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} +template +Span AsWritableBytes(Span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +Span MakeByteSpan(V&& v) noexcept +{ + return AsBytes(MakeSpan(std::forward(v))); +} +template +Span MakeWritableByteSpan(V&& v) noexcept +{ + return AsWritableBytes(MakeSpan(std::forward(v))); +} + // Helper functions to safely cast to unsigned char pointers. inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; } inline unsigned char* UCharCast(unsigned char* c) { return c; } inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; } inline const unsigned char* UCharCast(const unsigned char* c) { return c; } +inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast(c); } // Helper function to safely convert a Span to a Span<[const] unsigned char>. template constexpr auto UCharSpanCast(Span s) -> Span::type> { return {UCharCast(s.data()), s.size()}; } diff --git a/src/streams.h b/src/streams.h index 4df194db2d..7ddf405049 100644 --- a/src/streams.h +++ b/src/streams.h @@ -230,7 +230,7 @@ public: : nType{nTypeIn}, nVersion{nVersionIn} {} - explicit CDataStream(Span sp, int nTypeIn, int nVersionIn) + explicit CDataStream(Span sp, int nTypeIn, int nVersionIn) : vch(sp.data(), sp.data() + sp.size()), nType{nTypeIn}, nVersion{nVersionIn} {} @@ -258,17 +258,17 @@ public: iterator end() { return vch.end(); } size_type size() const { return vch.size() - nReadPos; } bool empty() const { return vch.size() == nReadPos; } - void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); } + void resize(size_type n, value_type c = value_type{}) { vch.resize(n + nReadPos, c); } void reserve(size_type n) { vch.reserve(n + nReadPos); } const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } reference operator[](size_type pos) { return vch[pos + nReadPos]; } void clear() { vch.clear(); nReadPos = 0; } - iterator insert(iterator it, const uint8_t x) { return vch.insert(it, x); } - void insert(iterator it, size_type n, const uint8_t x) { vch.insert(it, n, x); } + iterator insert(iterator it, const value_type x) { return vch.insert(it, x); } + void insert(iterator it, size_type n, const value_type x) { vch.insert(it, n, x); } value_type* data() { return vch.data() + nReadPos; } const value_type* data() const { return vch.data() + nReadPos; } - void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) + void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) { if (last == first) return; assert(last - first > 0); @@ -282,7 +282,7 @@ public: vch.insert(it, first, last); } - void insert(iterator it, const char* first, const char* last) + void insert(iterator it, const value_type* first, const value_type* last) { if (last == first) return; assert(last - first > 0); diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 714fccffaa..99f3ebdfa1 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -24,6 +24,16 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } + { + const std::vector in_u{0xff, 0x01, 0xff}; + const std::vector in_b{std::byte{0xff}, std::byte{0x01}, std::byte{0xff}}; + const std::string in_s{"\xff\x01\xff"}; + const std::string out_exp{"/wH/"}; + BOOST_CHECK_EQUAL(EncodeBase64(in_u), out_exp); + BOOST_CHECK_EQUAL(EncodeBase64(in_b), out_exp); + BOOST_CHECK_EQUAL(EncodeBase64(in_s), out_exp); + } + // Decoding strings with embedded NUL characters should fail bool failure; (void)DecodeBase64("invalid\0"s, &failure); diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index ba2d879bb7..7aa4d9b3c3 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); in.push_back('\x0f'); in.push_back('\xf0'); @@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); // Multi character key @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) ds.Xor(key); BOOST_CHECK_EQUAL( std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); + ds.str()); } BOOST_AUTO_TEST_CASE(streams_buffered_file) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 4095e2a739..c1fe68c870 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -186,12 +186,25 @@ BOOST_AUTO_TEST_CASE(util_HexStr) HexStr(Span(ParseHex_expected, ParseHex_expected)), ""); - std::vector ParseHex_vec(ParseHex_expected, ParseHex_expected + 5); + { + const std::vector in_s{ParseHex_expected, ParseHex_expected + 5}; + const Span in_u{MakeUCharSpan(in_s)}; + const Span in_b{MakeByteSpan(in_s)}; + const std::string out_exp{"04678afdb0"}; - BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec), - "04678afdb0" - ); + BOOST_CHECK_EQUAL(HexStr(in_u), out_exp); + BOOST_CHECK_EQUAL(HexStr(in_s), out_exp); + BOOST_CHECK_EQUAL(HexStr(in_b), out_exp); + } +} + +BOOST_AUTO_TEST_CASE(span_write_bytes) +{ + std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}}; + const auto mut_bytes{MakeWritableByteSpan(mut_arr)}; + mut_bytes[1] = std::byte{0x11}; + BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa); + BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11); } BOOST_AUTO_TEST_CASE(util_Join) diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 84d806d65a..ed4624c3c5 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -138,11 +138,6 @@ std::string EncodeBase64(Span input) return str; } -std::string EncodeBase64(const std::string& str) -{ - return EncodeBase64(MakeUCharSpan(str)); -} - std::vector DecodeBase64(const char* p, bool* pf_invalid) { static const int8_t decode64_table[256]{ diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 427f3e2651..ab5cf47adf 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -49,8 +49,8 @@ bool IsHexNumber(const std::string& str); std::vector DecodeBase64(const char* p, bool* pf_invalid = nullptr); std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); std::string EncodeBase64(Span input); -std::string EncodeBase64(const std::string& str); - +inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } +inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } std::vector DecodeBase32(const char* p, bool* pf_invalid = nullptr); std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr); @@ -194,6 +194,7 @@ std::optional ToIntegral(const std::string& str) */ std::string HexStr(const Span s); inline std::string HexStr(const Span s) { return HexStr(MakeUCharSpan(s)); } +inline std::string HexStr(const Span s) { return HexStr(MakeUCharSpan(s)); } /** * Format a paragraph of text to a fixed width, adding spaces for