Skip to content

Conversation

practicalswift
Copy link
Contributor

@practicalswift practicalswift commented Jul 19, 2018

Add error handling. Check return value of ParseUInt32(...) in ParseHDKeypath(...).

ParseUInt32(...) returns false if the entire string could not be parsed or when an overflow or underflow occurred. In such case the uninitialized variable number would be used in the calculation of path (prior to this commit).

An example key path triggering this is m/0/4294967296:

  ParseHDKeypath("m/0/4294967296", keypath);

4294967296 is 1 + 0xFFFFFFFF (uint32_t max: 4294967295).

Introduced in a4b06fb which was merged into master 14 hours ago as part of #13557 ("BIP 174 PSBT Serializations and RPCs").

@practicalswift practicalswift changed the title wallet: Add error handling. Check return value of ParseUInt32(...) in… wallet: Add error handling in ParseHDKeypath(...). Check return value of ParseUInt32(...) in… Jul 19, 2018
@practicalswift practicalswift changed the title wallet: Add error handling in ParseHDKeypath(...). Check return value of ParseUInt32(...) in… wallet: Fix non-determinism in ParseHDKeypath(...). Avoid using an uninitialized value in path calculation. Jul 19, 2018
@practicalswift practicalswift changed the title wallet: Fix non-determinism in ParseHDKeypath(...). Avoid using an uninitialized value in path calculation. wallet: Fix non-determinism in ParseHDKeypath(...). Avoid using an uninitialized variable in path calculation. Jul 19, 2018
@maflcko
Copy link
Member

maflcko commented Jul 19, 2018

Would be nice if this was covered by a test case, no?

@practicalswift practicalswift force-pushed the check-ParseUInt32-return-value branch from 7893b01 to f239417 Compare July 19, 2018 12:56
@practicalswift
Copy link
Contributor Author

practicalswift commented Jul 19, 2018

@MarcoFalke Thanks for the quick review. I've now added some tests.

This is the subset of the added tests that failed before the fix commit and passes after the fix commit:

wallet/test/psbt_wallet_tests.cpp(…): error: in "psbt_wallet_tests/parse_hd_keypath": 
  check !ParseHDKeypath("///////////////////////////", keypath) has failed
  check !ParseHDKeypath("//////////////////////////'/", keypath) has failed
  check !ParseHDKeypath("1///////////////////////////", keypath) has failed
  check !ParseHDKeypath("1/'//////////////////////////", keypath) has failed
  check !ParseHDKeypath("4294967296", keypath) has failed
  check !ParseHDKeypath("m/1/1/111111111111111111111111111111111111111111111111111111111111111111111111111111111111", keypath) has failed
  check !ParseHDKeypath("m/1//", keypath) has failed
  check !ParseHDKeypath("m/0/4294967296", keypath) has failed
  check !ParseHDKeypath("m/4294967296", keypath) has failed

Please re-review :-)

@practicalswift practicalswift force-pushed the check-ParseUInt32-return-value branch from f239417 to 44a5042 Compare July 19, 2018 13:38
@@ -31,4 +31,5 @@ bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
UniValue getaddressinfo(const JSONRPCRequest& request);
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type = 1, bool sign = true, bool bip32derivs = false);
bool ParseHDKeypath(std::string keypath_str, std::vector<uint32_t>& keypath);
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than declare it in the header, you could declare it extern in the test file.

@practicalswift practicalswift force-pushed the check-ParseUInt32-return-value branch from 44a5042 to 7e788ff Compare July 19, 2018 19:07
@laanwj laanwj added this to the 0.17.0 milestone Jul 19, 2018
@practicalswift practicalswift force-pushed the check-ParseUInt32-return-value branch from 7e788ff to 27ee53c Compare July 19, 2018 19:13
@achow101
Copy link
Member

utACK 7223263

@maflcko
Copy link
Member

maflcko commented Jul 19, 2018

utACK 7223263

@maflcko
Copy link
Member

maflcko commented Jul 19, 2018

utACK 27ee53c

1 similar comment
@sipa
Copy link
Member

sipa commented Jul 19, 2018

utACK 27ee53c

@maflcko maflcko merged commit 27ee53c into bitcoin:master Jul 19, 2018
maflcko pushed a commit that referenced this pull request Jul 19, 2018
…id using an uninitialized variable in path calculation.

27ee53c wallet: Add error handling. Check return value of ParseUInt32(...) in ParseHDKeypath(...). (practicalswift)
7223263 wallet: Add tests for ParseHDKeypath(...) (practicalswift)

Pull request description:

  Add error handling. Check return value of `ParseUInt32(...)` in `ParseHDKeypath(...)`.

  `ParseUInt32(...)` returns `false` if the entire string could not be parsed or when an overflow or underflow occurred. In such case the uninitialized variable `number` would be used in the calculation of `path` (prior to this commit).

  An example key path triggering this is `m/0/4294967296`:

  ```
    ParseHDKeypath("m/0/4294967296", keypath);
  ```

  `4294967296` is `1` + `0xFFFFFFFF` (`uint32_t` max: `4294967295`).

  Introduced in a4b06fb which was merged into `master` 14 hours ago as part of #13557 ("BIP 174 PSBT Serializations and RPCs").

Tree-SHA512: e5ff423f67c18d82c1231bde6343587a453e793c32004d93dc9b61be6d9372b57a6b2c9978d9eb1000d6cc82fd180f2486013f928dca737fb92daad22c16e467
@practicalswift
Copy link
Contributor Author

practicalswift commented Aug 2, 2018

@achow101 @MarcoFalke @sipa As reviewers of this bug fix you might be interested in reviewing PR #13815 which adds annotations (C++17-style [[nodiscard]] or __attribute__((warn_unused_result)) depending on availability) which could help us guard against unintentionally ignored return values going forward :-)

maflcko pushed a commit that referenced this pull request Nov 15, 2018
… functions returning bool

9cc0230 Add NODISCARD to all {Decode,Parse}[...](...) functions returning bool. Sort includes. (practicalswift)
579497e tests: Explicitly ignore the return value of DecodeBase58(...) (practicalswift)
145fe95 tests: Check return value of ParseParameters(...) (practicalswift)
7c5bc2a miner: Default to DEFAULT_BLOCK_MIN_TX_FEE if unable to parse -blockmintxfee (practicalswift)

Pull request description:

  Changes in this PR:
  * ~~Add linter to make sure the return value of `Parse[...](...)` is checked~~
  * Add `__attribute__((warn_unused_result))` to all `{Decode,Parse}[...](...)` functions returning `bool`
  * Fix violations

  Context:
  * #13712: `wallet: Fix non-determinism in ParseHDKeypath(...). Avoid using an uninitialized variable in path calculation.` would have been prevented by this

Tree-SHA512: 41a97899f2d5a26584235fa02b1ebfb4faacd81ea97e927022955a658fa7e15d07a1443b4b7635151a43259a1adf8f2f4de3c1c75d7b5f09f0d5496463a1dae6
@practicalswift practicalswift deleted the check-ParseUInt32-return-value branch April 10, 2021 19:35
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants