refactor: Avoid UB in SHA3_256::Write #31655

pull maflcko wants to merge 2 commits into bitcoin:master from maflcko:2501-less-ub changing 5 files +11 −11
  1. maflcko commented at 6:46 pm on January 14, 2025: member

    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 #31272.

    Also included is a somewhat unrelated commit.

  2. refactor: Drop unused UCharCast
    This is no longer needed after commit
    6aa0e70ccbd5491ec9d7c81892820f3341ccd631
    fad4032b21
  3. refactor: Avoid UB in SHA3_256::Write
    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.
    fabeca3458
  4. DrahtBot commented at 6:46 pm on January 14, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31655.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK sipa, theuni, hebasto

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  5. DrahtBot renamed this:
    refactor: Avoid UB in SHA3_256::Write
    refactor: Avoid UB in SHA3_256::Write
    on Jan 14, 2025
  6. DrahtBot added the label Refactoring on Jan 14, 2025
  7. maflcko commented at 6:48 pm on January 14, 2025: member
    I tested with g++-14 and the resulting bitcoind was unchanged, so I tagged this as “refactor”. However, this may not hold for every compiler and build setting.
  8. sipa commented at 6:56 pm on January 14, 2025: member
    utACK fabeca3458b38a3d8930cb0cbc866388c3f120f1
  9. maflcko commented at 8:10 pm on January 14, 2025: member

    This can be tested with a diff:

     0diff --git a/src/crypto/sha3.cpp b/src/crypto/sha3.cpp
     1index 770500bfe2..6eedba3ad6 100644
     2--- a/src/crypto/sha3.cpp
     3+++ b/src/crypto/sha3.cpp
     4@@ -103,8 +103,10 @@ void KeccakF(uint64_t (&st)[25])
     5     }
     6 }
     7 
     8-SHA3_256& SHA3_256::Write(Span<const unsigned char> data)
     9+#include <span>
    10+SHA3_256& SHA3_256::Write(Span<const unsigned char> old)
    11 {
    12+std::span data{old};
    13     if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
    14         // Fill the buffer and process it.
    15         std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
    

    On master it fails when running MAKEJOBS="-j$(nproc)" FILE_ENV="./ci/test/00_setup_env_native_msan.sh" ./ci/test_run_all.sh. On this pull, it should pass.

  10. theuni approved
  11. theuni commented at 10:15 pm on January 14, 2025: member
    utACK fabeca3458b38a3d8930cb0cbc866388c3f120f1
  12. maflcko added this to the milestone 29.0 on Jan 15, 2025
  13. hebasto commented at 10:51 am on January 16, 2025: member

    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.

    I’m not arguing with this change, but could someone provide a quote from the C++20 standard that stipulates this? From my reading of the standard, it appears that only dereferencing causes UB in such cases.

  14. maflcko commented at 11:13 am on January 16, 2025: member

    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.

    I’m not arguing with this change, but could someone provide a quote from the C++20 standard that stipulates this? From my reading of the standard, it appears that only dereferencing causes UB in such cases.

    No, the addition explicitly declares this as UB, see https://eel.is/c++draft/expr.add#4:

    When an expression J that has integral type is added to […] an expression P of pointer type, the result has the type of P. … if P points to a (possibly-hypothetical) array element i of an array object x with n elements […] the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element i+j of x if 0≤i+j≤n […] Otherwise, the behavior is undefined.

    Note: In the context of Span, an iterator is a pointer.

  15. hebasto commented at 11:39 am on January 16, 2025: member

    This can be tested with a diff:

     0diff --git a/src/crypto/sha3.cpp b/src/crypto/sha3.cpp
     1index 770500bfe2..6eedba3ad6 100644
     2--- a/src/crypto/sha3.cpp
     3+++ b/src/crypto/sha3.cpp
     4@@ -103,8 +103,10 @@ void KeccakF(uint64_t (&st)[25])
     5     }
     6 }
     7 
     8-SHA3_256& SHA3_256::Write(Span<const unsigned char> data)
     9+#include <span>
    10+SHA3_256& SHA3_256::Write(Span<const unsigned char> old)
    11 {
    12+std::span data{old};
    13     if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
    14         // Fill the buffer and process it.
    15         std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
    

    On master it fails when running MAKEJOBS="-j$(nproc)" FILE_ENV="./ci/test/00_setup_env_native_msan.sh" ./ci/test_run_all.sh. On this pull, it should pass.

    I can confirm this.

  16. hebasto approved
  17. hebasto commented at 11:42 am on January 16, 2025: member
    ACK fabeca3458b38a3d8930cb0cbc866388c3f120f1.
  18. fanquake merged this on Jan 16, 2025
  19. fanquake closed this on Jan 16, 2025

  20. maflcko deleted the branch on Jan 16, 2025

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-01-21 03:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me