refactor: Return uint64_t from GetSerializeSize #33724

pull maflcko wants to merge 6 commits into bitcoin:master from maflcko:2510-size-refactor changing 20 files +88 −81
  1. maflcko commented at 3:54 pm on October 28, 2025: member

    Consensus code should arrive at the same conclusion, regardless of the architecture it runs on. Using architecture-specific types such as size_t can lead to issues, such as the low-severity CVE-2025-46597.

    The CVE was already worked around, but it may be good to still fix the underlying issue.

    Fixes #33709 with a few refactors to use explicit fixed-sized integer types in serialization-size related code and concluding with a refactor to return uint64_t from GetSerializeSize. The refactors should not change any behavior, because the CVE was already worked around.

  2. test: Remove outdated comment
    The serialize related methods were removed in commit
    30007fda76aa7ba4e4090f7a16298874a7722926.
    
    If someone wants to see the tested methods, they can just read the test
    itself, instead of relying on the wrong comment.
    fa364af89b
  3. refactor: [rpc] Remove cast when reporting serialized size
    The values are small enough to fit in an int, so the cast is at best
    redundant. However, UniValue can handle any integer type, so having to
    think about the cast here is also confusing.
    fa2bbc9e4c
  4. move-only: Move CBlockFileInfo to kernel namespace
    Also, move it to the blockstorage module, because it is only used inside
    that module.
    
    Can be reviewed with the git option --color-moved=dimmed-zebra
    fa01f38e53
  5. DrahtBot renamed this:
    refactor: Return uint64_t from GetSerializeSize
    refactor: Return uint64_t from GetSerializeSize
    on Oct 28, 2025
  6. DrahtBot added the label Refactoring on Oct 28, 2025
  7. DrahtBot commented at 3:54 pm on October 28, 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/33724.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK darosior, hebasto, l0rinc

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33591 (Cluster mempool followups by sdaftuar)
    • #32427 ((RFC) kernel: Replace leveldb-based BlockTreeDB with flat-file based store by TheCharlatan)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  8. darosior commented at 4:40 pm on October 28, 2025: member
    Concept ACK.
  9. hebasto commented at 4:52 pm on October 28, 2025: member
    Concept ACK.
  10. l0rinc commented at 10:23 pm on October 28, 2025: contributor
    Concept ACK (only reviewed it lightly) - thanks for taking care of this, I will get back and review it more thoroughly!
  11. in src/index/blockfilterindex.cpp:205 in fadd49bd6d outdated
    201@@ -222,9 +202,9 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter&
    202 {
    203     assert(filter.GetFilterType() == GetFilterType());
    204 
    205-    size_t data_size =
    206+    uint64_t data_size{
    


    l0rinc commented at 12:26 pm on October 29, 2025:

    This value will be returned and converted to a size_t again https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/index/blockfilterindex.cpp#L201 and added to a FlatFilePos::nPos https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/index/blockfilterindex.cpp#L285 which is currently a uint32_t: https://github.com/bitcoin/bitcoin/blob/fa128d1488c08d9816f425c73d01db4c1597ee68/src/flatfile.h#L17

    Can we avoid converting this back and forth? I understand that we don’t have files that need gigabyte offsets - but in that case why convert to 64 bits here just to convert it back an forth later.



    maflcko commented at 8:40 am on October 30, 2025:

    This value will be returned and converted to a size_t again

    Correct, but this is safe, because the range was checked in the if below.

    Generally, the idea is that 32-bits is just not really enough to do size accounting (even on 32-bit architectures), because some code paths may accumulate sizes over time, or multiply them with a factor, all of which may or may not overflow the limited 32-bit value.

    So using 64-bit arithmetic is overall safer, and more future proof, because current and future reviewers have to think less about whether a 32-bit value may or may not overflow when doing arithmetic with it.

    Obviously, many 64-bit values will need to be cast to 32-bit later on for serialization, but this is generally only done after checking their range to ensure a safe cast. For example, in this case it is:

    0    if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
    

    nPos and MAX_FLTR_FILE_SIZE are 32-bit values, so if data_size was also 32-bit, the sum could overflow (theoretically) and incorrectly pass the if guard. Using 64-bit values here seems safer.

    I see in your branch that you want to change MAX_FLTR_FILE_SIZE to be 32-bit explicitly. However, I think it is safer to change it to 64-bit (or leave it as-is and rely on data_size being 64-bit).


    maflcko commented at 8:42 am on October 30, 2025:
    (see above)
  12. in src/rpc/blockchain.cpp:188 in fadd49bd6d outdated
    184@@ -185,9 +185,9 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
    185 {
    186     UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);
    187 
    188-    result.pushKV("strippedsize", (int)::GetSerializeSize(TX_NO_WITNESS(block)));
    189-    result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block)));
    190-    result.pushKV("weight", (int)::GetBlockWeight(block));
    191+    result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block)));
    


    l0rinc commented at 12:28 pm on October 29, 2025:
    is there any scenario where where a signed UniValue value is different from an unsigned one?

    maflcko commented at 8:42 am on October 30, 2025:

    Yes, a signed UniValue can be different here, when an overflow occurs. It would be represented as a string that starts with the - char.

    However, I don’t think an overflow can occur, as explained in the commit message.

  13. in src/rpc/blockchain.cpp:2036 in fadd49bd6d outdated
    2032@@ -2033,7 +2033,7 @@ static RPCHelpMan getblockstats()
    2033             for (const CTxOut& out : tx->vout) {
    2034                 tx_total_out += out.nValue;
    2035 
    2036-                size_t out_size = GetSerializeSize(out) + PER_UTXO_OVERHEAD;
    2037+                uint64_t out_size{GetSerializeSize(out) + PER_UTXO_OVERHEAD};
    


    l0rinc commented at 12:29 pm on October 29, 2025:

    Can we migrate the constant to 64 bits as well? https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/rpc/blockchain.cpp#L1907

    0static constexpr uint64_t PER_UTXO_OVERHEAD{sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool)};
    

    Or if we will go the other way and mirror storage and only up-cast when needed, it would be:

    0static constexpr uint32_t PER_UTXO_OVERHEAD{sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool)};
    

    maflcko commented at 8:42 am on October 30, 2025:

    Can we migrate the constant to 64 bits as well?

    Yes, happy to push that. (See my above comment why 64-bit is preferable)

  14. in src/node/blockstorage.cpp:1100 in fadd49bd6d
    1095@@ -1090,7 +1096,7 @@ bool BlockManager::ReadRawBlock(std::vector<std::byte>& block, const FlatFilePos
    1096 
    1097 FlatFilePos BlockManager::WriteBlock(const CBlock& block, int nHeight)
    1098 {
    1099-    const unsigned int block_size{static_cast<unsigned int>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    1100+    const auto block_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    1101     FlatFilePos pos{FindNextBlockPos(block_size + STORAGE_HEADER_BYTES, nHeight, block.GetBlockTime())};
    


    l0rinc commented at 12:44 pm on October 29, 2025:

    https://github.com/bitcoin/bitcoin/blob/fa128d1488c08d9816f425c73d01db4c1597ee68/src/node/blockstorage.h#L120 should also likely be updated now to:

    0static constexpr uint32_t STORAGE_HEADER_BYTES{std::tuple_size_v<MessageStartChars> + sizeof(uint32_t)};
    

    Note: I understand this works on most 32 bit systems we support, but https://en.cppreference.com/w/cpp/language/types.html indicates it can vary between 16 and 32 bits. Also, https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges warns:

    The int and unsigned int types have a size of 4 bytes. However, portable code shouldn’t depend on the size of int because the language standard allows this to be implementation-specific.

    https://godbolt.org/z/osrfrs8WW indicates both 32 and 64 bit platforms that I tried return 8 for STORAGE_HEADER_BYTES_OLD.


    maflcko commented at 8:42 am on October 30, 2025:
    Correct, but I wanted to keep this commit limited to just member fields, see #33724 (review). Happy to revert this hunk and leave if for a follow-up.
  15. in src/rpc/blockchain.cpp:190 in fadd49bd6d outdated
    184@@ -185,9 +185,9 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
    185 {
    186     UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);
    187 
    188-    result.pushKV("strippedsize", (int)::GetSerializeSize(TX_NO_WITNESS(block)));
    189-    result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block)));
    190-    result.pushKV("weight", (int)::GetBlockWeight(block));
    191+    result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block)));
    192+    result.pushKV("size", ::GetSerializeSize(TX_WITH_WITNESS(block)));
    193+    result.pushKV("weight", ::GetBlockWeight(block));
    


    l0rinc commented at 12:51 pm on October 29, 2025:

    maflcko commented at 8:42 am on October 30, 2025:

    Not sure I understand why GetBlockWeight is int64_t

    Generally, signed arithmetic types are preferred, when the values are later on used in arithmetic expressions. (Though, I don’t want to re-hash the discussion here and just focus on moving 32-bit to 64-bit unsigned arithmetic)

    but MAX_BLOCK_WEIGHT and MAX_BLOCK_SERIALIZED_SIZE are only unsigned int

    The type is sufficient to hold the value (also enforced at compile time by the compiler) and the type will promote itself seamlessly to work with 64-bit signed and unsigned arithmetic.

  16. in src/node/blockstorage.cpp:1102 in fadd49bd6d
    1095@@ -1090,7 +1096,7 @@ bool BlockManager::ReadRawBlock(std::vector<std::byte>& block, const FlatFilePos
    1096 
    1097 FlatFilePos BlockManager::WriteBlock(const CBlock& block, int nHeight)
    1098 {
    1099-    const unsigned int block_size{static_cast<unsigned int>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    1100+    const auto block_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    1101     FlatFilePos pos{FindNextBlockPos(block_size + STORAGE_HEADER_BYTES, nHeight, block.GetBlockTime())};
    1102     if (pos.IsNull()) {
    1103         LogError("FindNextBlockPos failed for %s while writing block", pos.ToString());
    


    l0rinc commented at 12:54 pm on October 29, 2025:

    FindNextBlockPos has unsigned int nAddSize arg still:

    0FlatFilePos BlockManager::FindNextBlockPos(uint32_t nAddSize, unsigned int nHeight, uint64_t nTime)
    

    maflcko commented at 8:42 am on October 30, 2025:
    Correct, but I wanted to keep this commit limited to just member fields, see #33724 (review). Happy to revert this hunk and leave if for a follow-up.
  17. in src/index/blockfilterindex.cpp:210 in fadd49bd6d outdated
    207         GetSerializeSize(filter.GetBlockHash()) +
    208-        GetSerializeSize(filter.GetEncodedFilter());
    209+        GetSerializeSize(filter.GetEncodedFilter())};
    210 
    211     // If writing the filter would overflow the file, flush and move to the next one.
    212     if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
    


    l0rinc commented at 1:14 pm on October 29, 2025:

    MAX_FLTR_FILE_SIZE is only used here https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/index/blockfilterindex.cpp#L39 we should adjust its type to match the usage

    0constexpr uint32_t FLTR_FILE_CHUNK_SIZE{0x100000}; // 1 MiB
    

    maflcko commented at 8:42 am on October 30, 2025:
    (see above)
  18. in src/serialize.h:1077 in fadd49bd6d outdated
    1081+        return *this;
    1082     }
    1083 
    1084-    size_t size() const {
    1085-        return nSize;
    1086+    uint64_t size() const
    


    l0rinc commented at 2:03 pm on October 29, 2025:

    maflcko commented at 8:45 am on October 30, 2025:
    Yeah, happy to push. I can see it go either way, because those return values are not primarily used in consensus, but rather try to mimic the std lib containers interface.

    l0rinc commented at 4:31 pm on October 30, 2025:
    These two are used in consensus code as well, that’s why I mentioned them. And they’re part of some template metaprogramming magic which should likely be aligned here. Will leave it up to you of course.

    maflcko commented at 4:44 pm on October 30, 2025:

    These two are used in consensus code as well,

    No, they are not. Only one of them is used in psbt, which is not consensus.

    One way to check if a function is used somewhere is to =delete it and compile.

    The following diff compiles:

     0diff --git a/src/psbt.h b/src/psbt.h
     1index f0de079f7b..ec235ed2fc 100644
     2--- a/src/psbt.h
     3+++ b/src/psbt.h
     4@@ -212,7 +212,7 @@ void DeserializeMuSig2ParticipantPubkeys(Stream& s, SpanReader& skey, std::map<C
     5     std::vector<unsigned char> val;
     6     s >> val;
     7     SpanReader s_val{val};
     8-    while (s_val.size() >= CPubKey::COMPRESSED_SIZE) {
     9+     {
    10         std::array<unsigned char, CPubKey::COMPRESSED_SIZE> part_pubkey_bytes;
    11         s_val >> std::as_writable_bytes(std::span{part_pubkey_bytes});
    12         participants.emplace_back(std::span{part_pubkey_bytes});
    13diff --git a/src/serialize.h b/src/serialize.h
    14index e88a25fa11..594fc72ef6 100644
    15--- a/src/serialize.h
    16+++ b/src/serialize.h
    17@@ -1127,7 +1127,7 @@ public:
    18     void read(std::span<std::byte> dst) { GetStream().read(dst); }
    19     void ignore(size_t num) { GetStream().ignore(num); }
    20     bool eof() const { return GetStream().eof(); }
    21-    size_t size() const { return GetStream().size(); }
    22+//    size_t size() const { return GetStream().size(); }
    23 
    24     //! Get reference to stream parameters.
    25     template <typename P>
    26diff --git a/src/streams.h b/src/streams.h
    27index 36af8dd615..d7e6c8de91 100644
    28--- a/src/streams.h
    29+++ b/src/streams.h
    30@@ -98,7 +98,7 @@ public:
    31         return (*this);
    32     }
    33 
    34-    size_t size() const { return m_data.size(); }
    35+    //size_t size() const { return m_data.size(); }
    36     bool empty() const { return m_data.empty(); }
    37 
    38     void read(std::span<std::byte> dst)
    
  19. in src/wallet/spend.cpp:1037 in fadd49bd6d outdated
    1033@@ -1034,7 +1034,7 @@ void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng_fast,
    1034     }
    1035 }
    1036 
    1037-size_t GetSerializeSizeForRecipient(const CRecipient& recipient)
    1038+uint64_t GetSerializeSizeForRecipient(const CRecipient& recipient)
    


    l0rinc commented at 2:16 pm on October 29, 2025:

    If we’re changing this, we should likely adjust the usage as well: https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/wallet/spend.cpp#L1085

    0    int32_t tx_noinputs_size = 0;
    

    maflcko commented at 8:42 am on October 30, 2025:
    I wanted to keep this one focussed on the kernel. Wallet changes can be done in a follow-up, if that is fine?

    l0rinc commented at 4:37 pm on October 30, 2025:
    Sure, but the smallest change here that would fix the bug would be to upcast the 4 multiplier to 64 bits as mentioned in #33724 (review). I don’t mind doing some combination of partial migration and not just the smallest possible diff, but I mentioned the outliers, will let you decide which ones are relevant and which ones to do separately. I don’t particularly care about the order.
  20. in src/node/blockstorage.cpp:907 in fadd49bd6d
    902@@ -897,7 +903,7 @@ void BlockManager::UpdateBlockInfo(const CBlock& block, unsigned int nHeight, co
    903     }
    904 
    905     // Update the file information with the current block.
    906-    const unsigned int added_size = ::GetSerializeSize(TX_WITH_WITNESS(block));
    907+    const auto added_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    908     const int nFile = pos.nFile;
    


    l0rinc commented at 3:11 pm on October 29, 2025:

    https://github.com/bitcoin/bitcoin/blob/fa128d1488c08d9816f425c73d01db4c1597ee68/src/flatfile.h#L16 is int32_t now so we should update these as well:

    0    const int32_t nFile = pos.nFile;
    1    if (static_cast<int32_t>(m_blockfile_info.size()) <= nFile) {
    

    maflcko commented at 8:42 am on October 30, 2025:
    Correct, but I wanted to keep this commit limited to just member fields, see #33724 (review). Happy to revert this hunk and leave if for a follow-up.
  21. in src/node/blockstorage.cpp:906 in fadd49bd6d
    902@@ -897,7 +903,7 @@ void BlockManager::UpdateBlockInfo(const CBlock& block, unsigned int nHeight, co
    903     }
    904 
    905     // Update the file information with the current block.
    906-    const unsigned int added_size = ::GetSerializeSize(TX_WITH_WITNESS(block));
    907+    const auto added_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
    


    l0rinc commented at 5:57 pm on October 29, 2025:
    It feels wrong to cast down on the client side, just to avoid incorrect serialization for the 64 bit version. We’re also storing these as 32 bits in many places, seems wrong to return 64 bits just because we will have a multiplication down the line. It seems like a code smell, I think we should go the other way instead: return an actual uint32_t size (which matches how we store and serialize these anyway) and only cast up before the problematic multiplications. Multiplying by static const uint64_t WITNESS_SCALE_FACTOR{4}; would already solve that without extra casts as far as I can tell.

    maflcko commented at 8:41 am on October 30, 2025:
    Yeah, I can go that way, but I think using 64-bit by default and explicitly casting after the range has been properly checked seems safer, see also #33724 (review)

    l0rinc commented at 4:38 pm on October 30, 2025:
    #33724 (review) explains it well, I can get behind both as long as we’re consistent

    maflcko commented at 4:54 pm on October 30, 2025:
    Dropped the blockstorage.cpp changes
  22. in src/coins.cpp:352 in fadd49bd6d outdated
    348@@ -349,8 +349,8 @@ void CCoinsViewCache::SanityCheck() const
    349     assert(recomputed_usage == cachedCoinsUsage);
    350 }
    351 
    352-static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut());
    353-static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT;
    354+static const uint64_t MIN_TRANSACTION_OUTPUT_WEIGHT{WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut())};
    


    l0rinc commented at 6:23 pm on October 29, 2025:
    storing MIN_TRANSACTION_OUTPUT_WEIGHT and WITNESS_SCALE_FACTOR as uint64_t would roughly fix the problem already, right? https://godbolt.org/z/M4dW3nsKM

    maflcko commented at 8:41 am on October 30, 2025:
    yes, but see above
  23. in src/flatfile.h:13 in fa128d1488 outdated
    12@@ -13,16 +13,16 @@
    13 
    


    TheCharlatan commented at 8:55 pm on October 29, 2025:

    In commit fa128d1488c08d9816f425c73d01db4c1597ee68:

    Would the return type of GetTotalSize fit into the criteria for this refactor?

     0diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
     1index cf6da55aa9..9d50dfe949 100644
     2--- a/src/blockencodings.cpp
     3+++ b/src/blockencodings.cpp
     4@@ -195 +195 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
     5-    unsigned int tx_missing_size = 0;
     6+    uint32_t tx_missing_size = 0;
     7diff --git a/src/net_processing.cpp b/src/net_processing.cpp
     8index 80902b9e9c..cfb5f80f6a 100644
     9--- a/src/net_processing.cpp
    10+++ b/src/net_processing.cpp
    11@@ -2474 +2474 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlo
    12-    unsigned int tx_requested_size = 0;
    13+    uint32_t tx_requested_size = 0;
    14diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
    15index e80ab60fcd..10c9361850 100644
    16--- a/src/primitives/transaction.cpp
    17+++ b/src/primitives/transaction.cpp
    18@@ -110 +110 @@ CAmount CTransaction::GetValueOut() const
    19-unsigned int CTransaction::GetTotalSize() const
    20+uint32_t CTransaction::GetTotalSize() const
    

    maflcko commented at 8:33 am on October 30, 2025:
    Good question. I wanted to keep it limited to member fields (and their constructors) only. Otherwise, there’d be way too many function calls to touch. Happy to do those in a follow-up. Also, happy to drop the src/node/blockstorage.cpp changes from this commit, to keep it more focussed on just member fields.
  24. l0rinc changes_requested
  25. l0rinc commented at 9:47 pm on October 29, 2025: contributor

    I like the focused commits with good explanations.

    I would like to suggest to consider something slightly simpler that may fit the data better. We’re storing these serialized sizes as 64 bits to avoid having to cast when we multiply the value. But we’re always serializing these sizes as either variable length ints or 32 bit ones, so it’s a bit awkward that a method returns 64 bit value and we just have to remember to cast them to 32 at call sites (otherwise they would serialize incorrectly in a few places). And we’re never actually multiplying by literals, so if we bump the multiplier to 64 bits (see branch below) and keep the serialization sizes at 32, we can avoid call-site casts and fx the overflow for free.

    I have recreated the entire change locally and compared it against your implementation and based on that added a few suggestion, please see them at https://github.com/l0rinc/bitcoin/pull/50/commits/9bb159736d6cc3d8ec67561279c2b9b4bf1129a0. They’re not necessarily all suggestions, some are just alternatives or nits, but please consider them. There are still a few inconsistencies that I would like to see patched here - and hope we can propagate these using the appropriate type instead of up-casting just to be absolutely sure…

  26. refactor: Use fixed size ints over (un)signed ints for serialized values
    Bitcoin Core already assumes that 'unsigned int' means uint32_t and
    'signed int' means int32_t. See src/compat/assumptions.h. Also, any
    serialized integral value must be of a fixed size.
    
    So make the fixed size explicit in this documenting refactor, which does
    not change the behavior on any platform.
    fa4f388fc9
  27. refactor: Use uint64_t over size_t for serialized-size values
    The values are small enough to fit in size_t, but to avoid having to
    think about it, just use uint64_t consistently for all architectures.
    
    On 64-bit systems, this refactor is a no-op. On 32-bit systems, it could
    avoid bugs in the theoretical and unexpected case where a 32-bit size_t
    is too small and overflows.
    fad0c8680e
  28. refactor: Return uint64_t from GetSerializeSize
    Normally, the values are small enough to fit in size_t, but the risk
    that it may not fit sometimes is a reason to use uint64_t consistently
    for all architectures.
    
    On 64-bit systems, this refactor is a no-op. On 32-bit systems, it could
    avoid bugs in the theoretical and unexpected case where a 32-bit size_t
    is too small and overflows.
    
    For example, 32-bit Bitcoin Core versions with CVE-2025-46597 unfixed
    may overflow while checking for the bad-blk-length violation when
    receiving a malformed and bloated compact block.
    fa6c0bedd3
  29. maflcko force-pushed on Oct 30, 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-11-02 12:13 UTC

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