Merge bitcoin/bitcoin#31655: refactor: Avoid UB in SHA3_256::Write

fabeca3458 refactor: Avoid UB in SHA3_256::Write (MarcoFalke)
fad4032b21 refactor: Drop unused UCharCast (MarcoFalke)

Pull request description:

  It is UB to apply a distance to a pointer or iterator further than the
  end itself, even if the distance is (partially) revoked later on.

  Fix the issue by advancing the data pointer at most to the end.

  This fix is required to adopt C++ safe buffers https://github.com/bitcoin/bitcoin/issues/31272.

  Also included is a somewhat unrelated commit.

ACKs for top commit:
  sipa:
    utACK fabeca3458
  theuni:
    utACK fabeca3458
  hebasto:
    ACK fabeca3458.

Tree-SHA512: 78c53691322b72c3ba9c25ec94eec275dbbbc3049b0ad45e7d9fb2df0afbbaa905b0d8fa7106a3582f937bb1dc15a7592c4ad2d80fe4cff1062a3acfd3638f08
This commit is contained in:
merge-script 2025-01-16 12:20:05 +00:00
commit 98939ce7b7
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1
5 changed files with 11 additions and 11 deletions

View File

@ -59,7 +59,7 @@ void ChaCha20Aligned::Seek(Nonce96 nonce, uint32_t block_counter) noexcept
inline void ChaCha20Aligned::Keystream(Span<std::byte> output) noexcept
{
unsigned char* c = UCharCast(output.data());
std::byte* c = output.data();
size_t blocks = output.size() / BLOCKLEN;
assert(blocks * BLOCKLEN == output.size());
@ -161,8 +161,8 @@ inline void ChaCha20Aligned::Keystream(Span<std::byte> output) noexcept
inline void ChaCha20Aligned::Crypt(Span<const std::byte> in_bytes, Span<std::byte> out_bytes) noexcept
{
assert(in_bytes.size() == out_bytes.size());
const unsigned char* m = UCharCast(in_bytes.data());
unsigned char* c = UCharCast(out_bytes.data());
const std::byte* m = in_bytes.data();
std::byte* c = out_bytes.data();
size_t blocks = out_bytes.size() / BLOCKLEN;
assert(blocks * BLOCKLEN == out_bytes.size());

View File

@ -56,8 +56,8 @@ void ComputeTag(ChaCha20& chacha20, Span<const std::byte> aad, Span<const std::b
poly1305.Update(cipher).Update(Span{PADDING}.first(cipher_padding_length));
// - Process the AAD and plaintext length with Poly1305.
std::byte length_desc[Poly1305::TAGLEN];
WriteLE64(UCharCast(length_desc), aad.size());
WriteLE64(UCharCast(length_desc + 8), cipher.size());
WriteLE64(length_desc, aad.size());
WriteLE64(length_desc + 8, cipher.size());
poly1305.Update(length_desc);
// Output tag.

View File

@ -105,9 +105,9 @@ void KeccakF(uint64_t (&st)[25])
SHA3_256& SHA3_256::Write(Span<const unsigned char> data)
{
if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
if (m_bufsize && data.size() >= sizeof(m_buffer) - m_bufsize) {
// Fill the buffer and process it.
std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
std::copy(data.begin(), data.begin() + (sizeof(m_buffer) - m_bufsize), m_buffer + m_bufsize);
data = data.subspan(sizeof(m_buffer) - m_bufsize);
m_state[m_pos++] ^= ReadLE64(m_buffer);
m_bufsize = 0;

View File

@ -268,12 +268,12 @@ public:
{
while (span.size() >= 8) {
uint64_t gen = Impl().rand64();
WriteLE64(UCharCast(span.data()), gen);
WriteLE64(span.data(), gen);
span = span.subspan(8);
}
if (span.size() >= 4) {
uint32_t gen = Impl().rand32();
WriteLE32(UCharCast(span.data()), gen);
WriteLE32(span.data(), gen);
span = span.subspan(4);
}
while (span.size()) {
@ -397,7 +397,7 @@ public:
if (requires_seed) RandomSeed();
std::array<std::byte, 8> buf;
rng.Keystream(buf);
return ReadLE64(UCharCast(buf.data()));
return ReadLE64(buf.data());
}
/** Fill a byte Span with random bytes. This overrides the RandomMixin version. */

View File

@ -603,7 +603,7 @@ void BerkeleyRODatabase::Open()
// Read subdatabase page number
// It is written as a big endian 32 bit number
uint32_t main_db_page = ReadBE32(UCharCast(std::get<DataRecord>(page.records.at(1)).data.data()));
uint32_t main_db_page = ReadBE32(std::get<DataRecord>(page.records.at(1)).data.data());
// The main database is in a page that doesn't exist
if (main_db_page > outer_meta.last_page) {