Skip to content

Commit

Permalink
Merge bitcoin/bitcoin#31655: refactor: Avoid UB in SHA3_256::Write
Browse files Browse the repository at this point in the history
fabeca3 refactor: Avoid UB in SHA3_256::Write (MarcoFalke)
fad4032 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 bitcoin/bitcoin#31272.

  Also included is a somewhat unrelated commit.

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

Tree-SHA512: 78c53691322b72c3ba9c25ec94eec275dbbbc3049b0ad45e7d9fb2df0afbbaa905b0d8fa7106a3582f937bb1dc15a7592c4ad2d80fe4cff1062a3acfd3638f08
  • Loading branch information
fanquake committed Jan 16, 2025
2 parents 712cab3 + fabeca3 commit 98939ce
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 11 deletions.
6 changes: 3 additions & 3 deletions src/crypto/chacha20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -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());

Expand Down
4 changes: 2 additions & 2 deletions src/crypto/chacha20poly1305.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/sha3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,12 @@ class RandomMixin
{
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()) {
Expand Down Expand Up @@ -397,7 +397,7 @@ class FastRandomContext : public RandomMixin<FastRandomContext>
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. */
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/migrate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 98939ce

Please sign in to comment.