diff options
author | MarcoFalke <falke.marco@gmail.com> | 2020-03-26 20:23:49 -0400 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2020-03-26 20:25:55 -0400 |
commit | 0dc6218c7911762027f7839f54b5d27845531255 (patch) | |
tree | bb036188d36b805d0aaa74440ff7df0dfe63c0d8 | |
parent | 7f9dedb22dcd9550ca525c0e35fec38b2d59e029 (diff) | |
parent | 100213c5c29ebd7bd50aa885e54594ae10bf87a4 (diff) | |
download | bitcoin-0dc6218c7911762027f7839f54b5d27845531255.tar.xz |
Merge #18270: util: Fail to parse whitespace-only strings in ParseMoney(...) (instead of parsing as zero)
100213c5c29ebd7bd50aa885e54594ae10bf87a4 util: Fail to parse space-only strings in ParseMoney(...) (instead of parsing as zero) (practicalswift)
Pull request description:
Fail to parse whitespace-only strings in `ParseMoney(...)` (instead of parsing as `0`).
This is a follow-up to #18225 ("util: Fail to parse empty string in `ParseMoney`") which made `ParseMoney("")` fail instead of parsing as `0`.
Context: https://github.com/bitcoin/bitcoin/pull/18225#issuecomment-592994765
Current non-test call sites:
```
$ git grep ParseMoney ":(exclude)src/test/"
src/bitcoin-tx.cpp: if (!ParseMoney(strValue, value))
src/init.cpp: if (!ParseMoney(gArgs.GetArg("-incrementalrelayfee", ""), n))
src/init.cpp: if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) {
src/init.cpp: if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n))
src/init.cpp: if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n))
src/miner.cpp: if (gArgs.IsArgSet("-blockmintxfee") && ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) {
src/util/moneystr.cpp:bool ParseMoney(const std::string& str, CAmount& nRet)
src/util/moneystr.h:NODISCARD bool ParseMoney(const std::string& str, CAmount& nRet);
src/wallet/wallet.cpp: if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
src/wallet/wallet.cpp: if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
src/wallet/wallet.cpp: if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
src/wallet/wallet.cpp: if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
src/wallet/wallet.cpp: if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
```
ACKs for top commit:
Empact:
ACK https://github.com/bitcoin/bitcoin/pull/18270/commits/100213c5c29ebd7bd50aa885e54594ae10bf87a4
sipa:
ACK 100213c5c29ebd7bd50aa885e54594ae10bf87a4
theStack:
ACK https://github.com/bitcoin/bitcoin/commit/100213c5c29ebd7bd50aa885e54594ae10bf87a4
Tree-SHA512: cadfb1ac8276cf54736c3444705f2650e7a08023673aedc729fabe751ae80f6c490fc0945ee38dbfd02c95e4d9853d1e4c84f5d3c310f44eaf3585afec8a4c22
-rw-r--r-- | src/test/util_tests.cpp | 20 | ||||
-rw-r--r-- | src/util/moneystr.cpp | 16 |
2 files changed, 27 insertions, 9 deletions
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index ab437d12a1..73b37f909f 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1182,6 +1182,12 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney) BOOST_CHECK_EQUAL(ret, COIN); BOOST_CHECK(ParseMoney("1", ret)); BOOST_CHECK_EQUAL(ret, COIN); + BOOST_CHECK(ParseMoney(" 1", ret)); + BOOST_CHECK_EQUAL(ret, COIN); + BOOST_CHECK(ParseMoney("1 ", ret)); + BOOST_CHECK_EQUAL(ret, COIN); + BOOST_CHECK(ParseMoney(" 1 ", ret)); + BOOST_CHECK_EQUAL(ret, COIN); BOOST_CHECK(ParseMoney("0.1", ret)); BOOST_CHECK_EQUAL(ret, COIN/10); BOOST_CHECK(ParseMoney("0.01", ret)); @@ -1198,12 +1204,26 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney) BOOST_CHECK_EQUAL(ret, COIN/10000000); BOOST_CHECK(ParseMoney("0.00000001", ret)); BOOST_CHECK_EQUAL(ret, COIN/100000000); + BOOST_CHECK(ParseMoney(" 0.00000001 ", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100000000); + BOOST_CHECK(ParseMoney("0.00000001 ", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100000000); + BOOST_CHECK(ParseMoney(" 0.00000001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100000000); // Parsing amount that can not be represented in ret should fail BOOST_CHECK(!ParseMoney("0.000000001", ret)); // Parsing empty string should fail BOOST_CHECK(!ParseMoney("", ret)); + BOOST_CHECK(!ParseMoney(" ", ret)); + BOOST_CHECK(!ParseMoney(" ", ret)); + + // Parsing two numbers should fail + BOOST_CHECK(!ParseMoney("1 2", ret)); + BOOST_CHECK(!ParseMoney(" 1 2 ", ret)); + BOOST_CHECK(!ParseMoney(" 1.2 3 ", ret)); + BOOST_CHECK(!ParseMoney(" 1 2.3 ", ret)); // Attempted 63 bit overflow should fail BOOST_CHECK(!ParseMoney("92233720368.54775808", ret)); diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp index 40d8918dfc..544cfb58f9 100644 --- a/src/util/moneystr.cpp +++ b/src/util/moneystr.cpp @@ -31,12 +31,12 @@ std::string FormatMoney(const CAmount& n) } -bool ParseMoney(const std::string& str, CAmount& nRet) +bool ParseMoney(const std::string& money_string, CAmount& nRet) { - if (!ValidAsCString(str)) { + if (!ValidAsCString(money_string)) { return false; } - + const std::string str = TrimString(money_string); if (str.empty()) { return false; } @@ -44,8 +44,6 @@ bool ParseMoney(const std::string& str, CAmount& nRet) std::string strWhole; int64_t nUnits = 0; const char* p = str.c_str(); - while (IsSpace(*p)) - p++; for (; *p; p++) { if (*p == '.') @@ -60,14 +58,14 @@ bool ParseMoney(const std::string& str, CAmount& nRet) break; } if (IsSpace(*p)) - break; + return false; if (!IsDigit(*p)) return false; strWhole.insert(strWhole.end(), *p); } - for (; *p; p++) - if (!IsSpace(*p)) - return false; + if (*p) { + return false; + } if (strWhole.size() > 10) // guard against 63 bit overflow return false; if (nUnits < 0 || nUnits > COIN) |