Skip to content

Conversation

@ffranr
Copy link
Contributor

@ffranr ffranr commented May 18, 2025

Closes #2372

Thank you to @brunoerg for opening the issue.


Protect against overflows when parsing malformed Taproot BIP32 derivation fields. This ensures that deserialization fails safely if the declared number of leaf hashes would otherwise cause an integer overflow.

@ffranr
Copy link
Contributor Author

ffranr commented May 18, 2025

An alternative safeguard would be to explicitly cap numHashes at some chosen maximum. However, I couldn't find a BIP-defined upper bound for the number of leaf hashes.

Given that, I think it's more appropriate to rely on the natural limit imposed by uint64 overflow rather than introduce an arbitrary cap. This keeps the implementation simple and avoids enforcing assumptions not defined by the spec.

// 1 (leaf hash count) + (N × 32) + 4 (fingerprint) + 1 (empty path count)
//
// First, we calculate the total number of bytes for the leaf hashes.
totalHashesBytes, mulCarry := bits.Mul64(numHashes, 32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: when will the mulCarry or the addCarry be non-zero? Why is this method preferred than, say, just calculating 32 * numHashes + 6?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since numHashes is uint64, numHashes * 32 fits in 64 bits unless numHashes > 2^64 / 32. mulCarry will be non-zero only in that overflow case. Using bits.Mul64 is safer and explicit about overflow handling.

Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix. Though I think this can be simplified quite a bit.

@ffranr ffranr force-pushed the 2372-fix-bip32-derivation-overflow-bug branch 3 times, most recently from b4ef41a to 16450e3 Compare May 22, 2025 12:24
@coveralls
Copy link

coveralls commented May 22, 2025

Pull Request Test Coverage Report for Build 15211625047

Details

  • 32 of 38 (84.21%) changed or added relevant lines in 1 file are covered.
  • 3 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.03%) to 56.757%

Changes Missing Coverage Covered Lines Changed/Added Lines %
btcutil/psbt/taproot.go 32 38 84.21%
Files with Coverage Reduction New Missed Lines %
btcec/v2/schnorr/signature.go 1 81.68%
btcutil/gcs/gcs.go 1 80.95%
mempool/mempool.go 1 66.56%
Totals Coverage Status
Change from base Build 14871723979: 0.03%
Covered Lines: 31169
Relevant Lines: 54917

💛 - Coveralls

Protect against overflows when parsing malformed Taproot BIP32
derivation fields. This ensures that deserialization fails safely if the
declared number of leaf hashes would otherwise cause an integer
overflow.
@ffranr ffranr force-pushed the 2372-fix-bip32-derivation-overflow-bug branch from 16450e3 to 16c2b92 Compare May 22, 2025 12:34
@ffranr ffranr requested review from guggero and yyforyongyu May 22, 2025 12:43
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🎉

Cap the `value` slice to `MaxPsbtValueLength` to prevent potential
out-of-memory conditions during parsing. This ensures that total
allocation remains bounded and consistent with other PSBT fields.
Copy link
Collaborator

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM🌹

func ReadTaprootBip32Derivation(xOnlyPubKey,
value []byte) (*TaprootBip32Derivation, error) {

// This function allocates additional memory while parsing the serialized
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@yyforyongyu yyforyongyu merged commit 0cba26d into btcsuite:master Jun 6, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: panic on ReadTaprootBip32Derivation

4 participants