-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Fix signed integer overflow in prioritisetransaction RPC #23418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://godbolt.org/z/aWTKcM6db, I have a couple of suggestions:
- make TestAdd, TestAddMatrixOverflow, TestAddMatrix and AdditionOverflow constexpr b/c why not
- Consider replacing MaybeAdd with my implementation of MaybeAddRet, which returns a value instead of mutating a mutable reference, which enables MaybeAddRet to be constexpr. (they appear virtually equally efficient, especially when we take into account we'll be using trivial types with this) (I also think this just makes more sense for a function called "MaybeAdd" as opposed to "MaybeAddEquals" or smth else)
- Consider adding a
static_assert(std::is_trivial<T>::value);
to ensure we only are using trivial types
(also, I see that you weren't really asking for a review, but I just saw the PR and started poking around :D )
e8522d0
to
fa108c3
Compare
@MarcoFalke do you have an opinion about these suggestions? |
Yeah, MaybeAdd will be removed, in which case the suggestions won't apply. |
faa7d8a util: Add SaturatingAdd helper (MarcoFalke) Pull request description: Seems good to have this in the repo, as it might be needed to write cleaner code. For example: * bitcoin/bitcoin#24090 (comment) * bitcoin/bitcoin#23418 (comment) * ... ACKs for top commit: MarcoFalke: Added a test. Should be trivial to re-ACK with `git range-diff bitcoin-core/master fa90189cbf faa7d8a` klementtan: reACK faa7d8a vasild: ACK faa7d8a Tree-SHA512: d0e6efdba7dfcbdd16ab4539a7f5e45a97d17792e42586c3c52caaae3fc70612dc9e364359658de5de5718fb8c2a765a59ceb2230098355394fa067a9732bc2a
fa108c3
to
faa69b3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
concept ACK faa69b3
Very nice to get rid of a sanitizer suppression, and the fee delta for modified fees should be a CAmount
anyway. I have a small suggestion which is not really within scope of this PR, so feel freee to ignore.
faa69b3
to
fa28736
Compare
fa28736
to
fa46eec
Compare
fa131d5
to
fa59aef
Compare
Rebased and replied to all comments. Also changed the name of the update function. |
fa3d182
to
fac053d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fac053d
Consider #23418 (comment)
fac053d
to
fa471a7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fa471a7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebased onto latest master (7377ed7), was able to reproduce the bug both using RPC and fuzzing, and the bug is fixed using the PR (both ways).
You could make a couple of small fixes in the description: dot before /autogen.sh
, and add -chain=regtest
to the bitcoin-cli
command lines.
In the first commit message, s/tacked/tracked/.
lockPoints{lp}, | ||
nSizeWithDescendants{GetTxSize()}, | ||
nModFeesWithDescendants{nFee}, | ||
nSizeWithAncestors{GetTxSize()}, | ||
nModFeesWithAncestors{nFee}, | ||
nSigOpCostWithAncestors{sigOpCost} {} | ||
|
||
void CTxMemPoolEntry::UpdateFeeDelta(CAmount newFeeDelta) | ||
void CTxMemPoolEntry::UpdateModifiedFee(CAmount fee_diff) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a better name be IncrementModifiedFee
? The verb "update" isn't wrong, but it could mean simply setting a variable to a value (as in a simple assignment statement). The verb "increment" makes it clear that a variable, or, in this case, 3 variables, are being incremented by the argument. It's true that the previous name used the verb "update", so maybe it would be best to preserve that. But I just thought I'd mention it for consideration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but maybe this can be done as a follow up to also rename the Update*State
functions, which do the same thing, but are not touched in this pull request.
src/txmempool.cpp
Outdated
@@ -921,7 +925,7 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD | |||
delta += nFeeDelta; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delta
is now unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delta
is a mutable reference, so while the symbol itself isn't used after this line, the line can not be removed.
* feeDelta tracked the delta (to be applied on top of the actual fee) * m_modified_fee tracks the actual fee with the delta included * Instead of passing in the new total delta to the Updater, pass in by how much the total delta should be modified. This is needed for the next commit, but makes sense on its own because the same is done by UpdateDescendantState and UpdateAncestorState.
fa471a7
to
fa07f84
Compare
Thx, done. Also rebased to make testing easier. Should be trivial to re-ACK with git range-diff. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fa07f84
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fa07f84
Concept ACK, Approach ACK. The saturating approach (as discussed in today's PR review club) makes sense over alternative approaches. Reviewed code changes, didn't test unfortunately. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fa07f84
I reproduced the bug on master both using RPC and fuzzing, and the bug is fixed using the PR (both ways)/
…tion RPC fa07f84 Fix signed integer overflow in prioritisetransaction RPC (MarcoFalke) fa52cf8 refactor: Replace feeDelta by m_modified_fee (MarcoFalke) Pull request description: Signed integer overflow is UB in theory, but not in practice. Still, it would be nice to avoid this UB to allow Bitcoin Core to be compiled with sanitizers such as `-ftrapv` or ubsan. It is impossible to predict when and if an overflow occurs, since the overflow caused by a prioritisetransaction RPC might only be later hit when descendant txs are added to the mempool. Since it is impossible to predict reliably, leave it up to the user to use the RPC endpoint responsibly, considering their mempool limits and usage patterns. Fixes: bitcoin#20626 Fixes: bitcoin#20383 Fixes: bitcoin#19278 Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34146 / https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47132 ## Steps to reproduce Build the code without the changes in this pull. Make sure to pass the sanitizer flag: ``` ./autogen.sh && ./configure --with-sanitizers=signed-integer-overflow && make clean && make -j $(nproc) ``` ### Reproduce on RPC ``` ./src/bitcoind -chain=regtest -noprinttoconsole & ./src/bitcoin-cli -chain=regtest prioritisetransaction 00000000deadbeef00000000deadbeef00000000deadbeef00000000deadbeef 0 9123456789123456789 ./src/bitcoin-cli -chain=regtest prioritisetransaction 00000000deadbeef00000000deadbeef00000000deadbeef00000000deadbeef 0 9123456789123456789 |> txmempool.cpp:920:15: runtime error: signed integer overflow: 9123456789123456789 + 9123456789123456789 cannot be represented in type 'long int' ./src/bitcoin-cli -chain=regtest stop ``` ### By fuzzing ``` wget https://github.com/bitcoin/bitcoin/files/8921302/clusterfuzz-testcase-minimized-validation_load_mempool-5599531390074880.bin.txt FUZZ=validation_load_mempool ./src/test/fuzz/fuzz ./clusterfuzz-testcase-minimized-validation_load_mempool-5599531390074880.bin.txt |> txmempool.cpp:920:15: runtime error: signed integer overflow: 7214801925397553184 + 2314885530818453536 cannot be represented in type 'long int' |> validation_load_mempool: succeeded against 1 files in 0s. ACKs for top commit: vasild: ACK fa07f84 dunxen: ACK fa07f84 LarryRuane: ACK fa07f84 Tree-SHA512: 4a357950af55a49c9113da0a50c2e743c5b752f0514dd8d16cd92bfde2f77dd0ef56aa98452626df6f7f7a5b51d1227021f6bc94091201a179f0d488ee32a0df
Signed integer overflow is UB in theory, but not in practice. Still,
it would be nice to avoid this UB to allow Bitcoin Core to be
compiled with sanitizers such as
-ftrapv
or ubsan.It is impossible to predict when and if an overflow occurs, since
the overflow caused by a prioritisetransaction RPC might only be
later hit when descendant txs are added to the mempool.
Since it is impossible to predict reliably, leave it up to the user
to use the RPC endpoint responsibly, considering their mempool
limits and usage patterns.
Fixes: #20626
Fixes: #20383
Fixes: #19278
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34146 / https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47132
Steps to reproduce
Build the code without the changes in this pull.
Make sure to pass the sanitizer flag:
Reproduce on RPC
By fuzzing