Skip to content
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

CExtKey::Unserialize and CExtPubKey::Unserialize throw std::runtime_error instead of the expected std::ios_base::failure #17130

Closed
practicalswift opened this issue Oct 13, 2019 · 11 comments

Comments

@practicalswift
Copy link
Contributor

practicalswift commented Oct 13, 2019

CExtKey::Unserialize(...) and CExtPubKey::Unserialize(...) throw std::runtime_error instead of the expected std::ios_base::failure.

Context (taken from an e-mail):

When fuzzing some deserialization code I noticed that CExtKey::Unserialize(...) and CExtPubKey::Unserialize(...) throw std::runtime_error instead of the std::ios_base::failure I expected in case of deserialization errors.

I saw that this code was written by you originally: do you remember if there was a particular reason to go with std::runtime_error instead of std::ios_base::failure? If not, do you think it would be safe to change it? :)

Code:

bitcoin/src/key.h

Lines 174 to 183 in 376638a

template <typename Stream>
void Unserialize(Stream& s)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
if (len != BIP32_EXTKEY_SIZE)
throw std::runtime_error("Invalid extended key size\n");
s.read((char *)&code[0], len);
Decode(code);
}

bitcoin/src/pubkey.h

Lines 240 to 249 in 78dae8c

template <typename Stream>
void Unserialize(Stream& s)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
if (len != BIP32_EXTKEY_SIZE)
throw std::runtime_error("Invalid extended key size\n");
s.read((char *)&code[0], len);
Decode(code);
}

FWIW the code paths in question are reachable by the fuzzers added in PR #17051 ("tests: Add deserialization fuzzing harnesses").

@practicalswift
Copy link
Contributor Author

Friendly ping @jonasschnelli :)

Could you clarify? This is a fuzzing blocker I'd like to get rid of if possible :)

@maflcko
Copy link
Member

maflcko commented Oct 16, 2019

Those messages are not sent over p2p, so fuzzing is nice to have, but not going to harden the protocol layer.

I guess they might be written by the wallet? In that case, you might want to check if the wallet is handling those exceptions properly.

@practicalswift
Copy link
Contributor Author

practicalswift commented Oct 18, 2019

The only use of CExt{Pub,}Key serialisation/deserialisation appears to be in bip32_tests:

CDataStream ssPub(SER_DISK, CLIENT_VERSION);
ssPub << pubkeyNew;
BOOST_CHECK(ssPub.size() == 75);
CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
ssPriv << keyNew;
BOOST_CHECK(ssPriv.size() == 75);
CExtPubKey pubCheck;
CExtKey privCheck;
ssPub >> pubCheck;
ssPriv >> privCheck;
BOOST_CHECK(pubCheck == pubkeyNew);
BOOST_CHECK(privCheck == keyNew);

I cannot find any non-test usage.

@maflcko
Copy link
Member

maflcko commented Oct 18, 2019

Maybe you can remove that logic then?

@achow101
Copy link
Member

I'm pretty sure serialization is used by the wallet for the dumpwallet rpc. Also, both are being used in #16463

@practicalswift
Copy link
Contributor Author

@achow101 dumpwallet is using EncodeExtKey, no? :)

// add the base58check encoded extended master if the wallet uses HD
CKeyID seed_id = pwallet->GetHDChain().seed_id;
if (!seed_id.IsNull())
{
CKey seed;
if (pwallet->GetKey(seed_id, seed)) {
CExtKey masterKey;
masterKey.SetSeed(seed.begin(), seed.size());
file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n";
}
}

@achow101
Copy link
Member

Hmm, so the actual serialization happens in Encode/Decode, not Serialize/Unserialize, and that's what #16463 uses. So in that case, I think it is fine to get rid of Serialize/Unserialize.

@practicalswift
Copy link
Contributor Author

practicalswift commented Oct 18, 2019

@MarcoFalke

Maybe you can remove that logic then?

Since #15814 + #15814 (comment) I'm a bit hesitant to touch dead code :)

Perhaps we can put a "good first issue" tag on this one and let a newcomer take care of the removal.

From a fuzzing perspective I've got my needs covered: if this code isn't used it doesn't matter if invalid deserialisation input makes it throw an unexpected exception type (std::runtime_error instead of the expected std::ios_base::failure). My job here is done :)

@maflcko
Copy link
Member

maflcko commented Oct 18, 2019

Ok, will add "good first issue"

@maflcko
Copy link
Member

maflcko commented Oct 18, 2019

Removing is probably fine. If this will ever be needed, a simple git revert $commit_that_removed_it should restore it.

maflcko pushed a commit to maflcko/bitcoin-core that referenced this issue Oct 24, 2019
…ization methods

5b44a75 refactor: Remove unused CExt{Pub,}Key (de)serialization methods (Sebastian Falbesoner)

Pull request description:

  As pointed out in issue bitcoin#17130, the serialization/deserialization methods for the classes `CExtKey` and
  `CExtPubKey` are only used in the BIP32 unit tests and hence can be removed (see comments bitcoin#17130 (comment), bitcoin#17130 (comment) and bitcoin#17130 (comment)).

ACKs for top commit:
  practicalswift:
    ACK 5b44a75 -- -60 LOC diff looks correct :)
  promag:
    ACK 5b44a75.
  MarcoFalke:
    unsigned ACK 5b44a75
  fjahr:
    ACK 5b44a75
  jonatack:
    Light ACK 5b44a75. Built, ran tests and bitcoind. `git blame` shows most of the last changes are from commit 90604f1 in 2015 to add bip32 pubkey serialization.

Tree-SHA512: 6887573b76b9e54e117a076557407b6f7908719b2202fb9eea498522baf9f30198b3f78b87a62efcd17ad1ab0886196f099239992ce7cbbaee79979ffe9e5f2c
@practicalswift
Copy link
Contributor Author

This was solved with the merge of #17212. Closing. Thanks @theStack! :)

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this issue Sep 11, 2021
…ization methods

5b44a75 refactor: Remove unused CExt{Pub,}Key (de)serialization methods (Sebastian Falbesoner)

Pull request description:

  As pointed out in issue bitcoin#17130, the serialization/deserialization methods for the classes `CExtKey` and
  `CExtPubKey` are only used in the BIP32 unit tests and hence can be removed (see comments bitcoin#17130 (comment), bitcoin#17130 (comment) and bitcoin#17130 (comment)).

ACKs for top commit:
  practicalswift:
    ACK 5b44a75 -- -60 LOC diff looks correct :)
  promag:
    ACK 5b44a75.
  MarcoFalke:
    unsigned ACK 5b44a75
  fjahr:
    ACK 5b44a75
  jonatack:
    Light ACK 5b44a75. Built, ran tests and bitcoind. `git blame` shows most of the last changes are from commit 90604f1 in 2015 to add bip32 pubkey serialization.

Tree-SHA512: 6887573b76b9e54e117a076557407b6f7908719b2202fb9eea498522baf9f30198b3f78b87a62efcd17ad1ab0886196f099239992ce7cbbaee79979ffe9e5f2c
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this issue Sep 11, 2021
…ization methods

5b44a75 refactor: Remove unused CExt{Pub,}Key (de)serialization methods (Sebastian Falbesoner)

Pull request description:

  As pointed out in issue bitcoin#17130, the serialization/deserialization methods for the classes `CExtKey` and
  `CExtPubKey` are only used in the BIP32 unit tests and hence can be removed (see comments bitcoin#17130 (comment), bitcoin#17130 (comment) and bitcoin#17130 (comment)).

ACKs for top commit:
  practicalswift:
    ACK 5b44a75 -- -60 LOC diff looks correct :)
  promag:
    ACK 5b44a75.
  MarcoFalke:
    unsigned ACK 5b44a75
  fjahr:
    ACK 5b44a75
  jonatack:
    Light ACK 5b44a75. Built, ran tests and bitcoind. `git blame` shows most of the last changes are from commit 90604f1 in 2015 to add bip32 pubkey serialization.

Tree-SHA512: 6887573b76b9e54e117a076557407b6f7908719b2202fb9eea498522baf9f30198b3f78b87a62efcd17ad1ab0886196f099239992ce7cbbaee79979ffe9e5f2c
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this issue Sep 12, 2021
…ization methods

5b44a75 refactor: Remove unused CExt{Pub,}Key (de)serialization methods (Sebastian Falbesoner)

Pull request description:

  As pointed out in issue bitcoin#17130, the serialization/deserialization methods for the classes `CExtKey` and
  `CExtPubKey` are only used in the BIP32 unit tests and hence can be removed (see comments bitcoin#17130 (comment), bitcoin#17130 (comment) and bitcoin#17130 (comment)).

ACKs for top commit:
  practicalswift:
    ACK 5b44a75 -- -60 LOC diff looks correct :)
  promag:
    ACK 5b44a75.
  MarcoFalke:
    unsigned ACK 5b44a75
  fjahr:
    ACK 5b44a75
  jonatack:
    Light ACK 5b44a75. Built, ran tests and bitcoind. `git blame` shows most of the last changes are from commit 90604f1 in 2015 to add bip32 pubkey serialization.

Tree-SHA512: 6887573b76b9e54e117a076557407b6f7908719b2202fb9eea498522baf9f30198b3f78b87a62efcd17ad1ab0886196f099239992ce7cbbaee79979ffe9e5f2c
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this issue Sep 12, 2021
…ization methods

5b44a75 refactor: Remove unused CExt{Pub,}Key (de)serialization methods (Sebastian Falbesoner)

Pull request description:

  As pointed out in issue bitcoin#17130, the serialization/deserialization methods for the classes `CExtKey` and
  `CExtPubKey` are only used in the BIP32 unit tests and hence can be removed (see comments bitcoin#17130 (comment), bitcoin#17130 (comment) and bitcoin#17130 (comment)).

ACKs for top commit:
  practicalswift:
    ACK 5b44a75 -- -60 LOC diff looks correct :)
  promag:
    ACK 5b44a75.
  MarcoFalke:
    unsigned ACK 5b44a75
  fjahr:
    ACK 5b44a75
  jonatack:
    Light ACK 5b44a75. Built, ran tests and bitcoind. `git blame` shows most of the last changes are from commit 90604f1 in 2015 to add bip32 pubkey serialization.

Tree-SHA512: 6887573b76b9e54e117a076557407b6f7908719b2202fb9eea498522baf9f30198b3f78b87a62efcd17ad1ab0886196f099239992ce7cbbaee79979ffe9e5f2c
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Dec 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants