From c1d165a8c2678c31aced5e1d46231d9996b0774a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 11:08:08 -0400 Subject: Make ParseHex use string_view --- src/util/strencodings.cpp | 30 +++++++++++------------------- src/util/strencodings.h | 3 +-- 2 files changed, 12 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 940fa90da2..f5288eca17 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -81,32 +81,24 @@ bool IsHexNumber(const std::string& str) return (str.size() > starting_location); } -std::vector ParseHex(const char* psz) +std::vector ParseHex(std::string_view str) { // convert hex dump to vector std::vector vch; - while (true) - { - while (IsSpace(*psz)) - psz++; - signed char c = HexDigit(*psz++); - if (c == (signed char)-1) - break; - auto n{uint8_t(c << 4)}; - c = HexDigit(*psz++); - if (c == (signed char)-1) - break; - n |= c; - vch.push_back(n); + auto it = str.begin(); + while (it != str.end() && it + 1 != str.end()) { + if (IsSpace(*it)) { + ++it; + continue; + } + auto c1 = HexDigit(*(it++)); + auto c2 = HexDigit(*(it++)); + if (c1 < 0 || c2 < 0) break; + vch.push_back(uint8_t(c1 << 4) | c2); } return vch; } -std::vector ParseHex(const std::string& str) -{ - return ParseHex(str.c_str()); -} - void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut) { size_t colon = in.find_last_of(':'); diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 1f83fa3ffa..0e72466fc3 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -55,8 +55,7 @@ enum class ByteUnit : uint64_t { * @return A new string without unsafe chars */ std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT); -std::vector ParseHex(const char* psz); -std::vector ParseHex(const std::string& str); +std::vector ParseHex(std::string_view str); signed char HexDigit(char c); /* Returns true if each character in str is a hex character, and has an even * number of hex digits.*/ -- cgit v1.2.3 From 40062997f223d88d4f92aaae4622a31476686163 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 11:12:04 -0400 Subject: Make IsHex use string_view --- src/util/strencodings.cpp | 8 +++----- src/util/strencodings.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index f5288eca17..7e7e7e2003 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -58,12 +58,10 @@ signed char HexDigit(char c) return p_util_hexdigit[(unsigned char)c]; } -bool IsHex(const std::string& str) +bool IsHex(std::string_view str) { - for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) - { - if (HexDigit(*it) < 0) - return false; + for (char c : str) { + if (HexDigit(c) < 0) return false; } return (str.size() > 0) && (str.size()%2 == 0); } diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 0e72466fc3..67baaaeca0 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -59,7 +59,7 @@ std::vector ParseHex(std::string_view str); signed char HexDigit(char c); /* Returns true if each character in str is a hex character, and has an even * number of hex digits.*/ -bool IsHex(const std::string& str); +bool IsHex(std::string_view str); /** * Return true if the string is a hex number, optionally prefixed with "0x" */ -- cgit v1.2.3 From 963bc9b576f0a62caffede2ce32830aef3473995 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 11:20:10 -0400 Subject: Make IsHexNumber use string_view --- src/util/strencodings.cpp | 11 ++++------- src/util/strencodings.h | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 7e7e7e2003..9a6883228f 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -66,17 +66,14 @@ bool IsHex(std::string_view str) return (str.size() > 0) && (str.size()%2 == 0); } -bool IsHexNumber(const std::string& str) +bool IsHexNumber(std::string_view str) { - size_t starting_location = 0; - if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') { - starting_location = 2; - } - for (const char c : str.substr(starting_location)) { + if (str.substr(0, 2) == "0x") str.remove_prefix(2); + for (char c : str) { if (HexDigit(c) < 0) return false; } // Return false for empty string or "0x". - return (str.size() > starting_location); + return str.size() > 0; } std::vector ParseHex(std::string_view str) diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 67baaaeca0..678f42cb06 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -63,7 +63,7 @@ bool IsHex(std::string_view str); /** * Return true if the string is a hex number, optionally prefixed with "0x" */ -bool IsHexNumber(const std::string& str); +bool IsHexNumber(std::string_view str); std::vector DecodeBase64(const char* p, bool* pf_invalid = nullptr); std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); std::string EncodeBase64(Span input); -- cgit v1.2.3 From d648b5120b2fefa9e599898bd26f05ecf4428fac Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 11:23:03 -0400 Subject: Make SanitizeString use string_view --- src/util/strencodings.cpp | 14 +++++++------- src/util/strencodings.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 9a6883228f..6346bc0811 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -24,15 +24,15 @@ static const std::string SAFE_CHARS[] = CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI }; -std::string SanitizeString(const std::string& str, int rule) +std::string SanitizeString(std::string_view str, int rule) { - std::string strResult; - for (std::string::size_type i = 0; i < str.size(); i++) - { - if (SAFE_CHARS[rule].find(str[i]) != std::string::npos) - strResult.push_back(str[i]); + std::string result; + for (char c : str) { + if (SAFE_CHARS[rule].find(c) != std::string::npos) { + result.push_back(c); + } } - return strResult; + return result; } const signed char p_util_hexdigit[256] = diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 678f42cb06..82645c6bf0 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -54,7 +54,7 @@ enum class ByteUnit : uint64_t { * @param[in] rule The set of safe chars to choose (default: least restrictive) * @return A new string without unsafe chars */ -std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT); +std::string SanitizeString(std::string_view str, int rule = SAFE_CHARS_DEFAULT); std::vector ParseHex(std::string_view str); signed char HexDigit(char c); /* Returns true if each character in str is a hex character, and has an even -- cgit v1.2.3 From a4377a0843636eae0aaf698510fc6518582545db Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 8 Apr 2022 23:17:01 -0400 Subject: Reject incorrect base64 in HTTP auth In addition, to make sure that no call site ignores the invalid decoding status, make the pf_invalid argument mandatory. --- src/httprpc.cpp | 4 +++- src/test/base32_tests.cpp | 4 +++- src/test/base64_tests.cpp | 4 +++- src/util/strencodings.cpp | 12 ++++-------- src/util/strencodings.h | 8 ++++---- 5 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 5d0b59f7cb..5d62568343 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -132,7 +132,9 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna if (strAuth.substr(0, 6) != "Basic ") return false; std::string strUserPass64 = TrimString(strAuth.substr(6)); - std::string strUserPass = DecodeBase64(strUserPass64); + bool invalid; + std::string strUserPass = DecodeBase64(strUserPass64, &invalid); + if (invalid) return false; if (strUserPass.find(':') != std::string::npos) strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':')); diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 5fab7f0d1e..8a44e65165 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -22,7 +22,9 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); strEnc = EncodeBase32(vstrIn[i], false); BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]); - std::string strDec = DecodeBase32(vstrOut[i]); + bool invalid; + std::string strDec = DecodeBase32(vstrOut[i], &invalid); + BOOST_CHECK(!invalid); BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 6ee1b83691..04b5185653 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -19,7 +19,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) { std::string strEnc = EncodeBase64(vstrIn[i]); BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); - std::string strDec = DecodeBase64(strEnc); + bool invalid; + std::string strDec = DecodeBase64(strEnc, &invalid); + BOOST_CHECK(!invalid); BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 6346bc0811..6b6644aa9f 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -167,7 +167,7 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 4 == 0 && p - q < 4; - if (pf_invalid) *pf_invalid = !valid; + *pf_invalid = !valid; return ret; } @@ -175,9 +175,7 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) std::string DecodeBase64(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { - if (pf_invalid) { - *pf_invalid = true; - } + *pf_invalid = true; return {}; } std::vector vchRet = DecodeBase64(str.c_str(), pf_invalid); @@ -245,7 +243,7 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 8 == 0 && p - q < 8; - if (pf_invalid) *pf_invalid = !valid; + *pf_invalid = !valid; return ret; } @@ -253,9 +251,7 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) std::string DecodeBase32(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { - if (pf_invalid) { - *pf_invalid = true; - } + *pf_invalid = true; return {}; } std::vector vchRet = DecodeBase32(str.c_str(), pf_invalid); diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 82645c6bf0..c87b2d2415 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -64,13 +64,13 @@ bool IsHex(std::string_view str); * Return true if the string is a hex number, optionally prefixed with "0x" */ bool IsHexNumber(std::string_view str); -std::vector DecodeBase64(const char* p, bool* pf_invalid = nullptr); -std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); +std::vector DecodeBase64(const char* p, bool* pf_invalid); +std::string DecodeBase64(const std::string& str, bool* pf_invalid); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } -std::vector DecodeBase32(const char* p, bool* pf_invalid = nullptr); -std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr); +std::vector DecodeBase32(const char* p, bool* pf_invalid); +std::string DecodeBase32(const std::string& str, bool* pf_invalid); /** * Base32 encode. -- cgit v1.2.3 From a65931e3ce66d87b8f83d67ecdbb46f137e6a670 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 13:19:49 -0400 Subject: Make DecodeBase{32,64} always return vector, not string Base32/base64 are mechanisms for encoding binary data. That they'd decode to a string is just bizarre. The fact that they'd do that based on the type of input arguments even more so. --- src/httprpc.cpp | 3 ++- src/i2p.cpp | 2 +- src/netaddress.cpp | 2 +- src/psbt.cpp | 8 ++++---- src/psbt.h | 2 +- src/qt/walletframe.cpp | 6 +++--- src/test/base32_tests.cpp | 4 ++-- src/test/base64_tests.cpp | 4 ++-- src/test/fuzz/base_encode_decode.cpp | 8 ++++---- src/test/fuzz/psbt.cpp | 6 ++++-- src/util/message.cpp | 2 +- src/util/strencodings.cpp | 10 ++++------ src/util/strencodings.h | 4 ++-- 13 files changed, 31 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 5d62568343..96cccd8de9 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -133,8 +133,9 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna return false; std::string strUserPass64 = TrimString(strAuth.substr(6)); bool invalid; - std::string strUserPass = DecodeBase64(strUserPass64, &invalid); + std::vector userpass_data = DecodeBase64(strUserPass64, &invalid); if (invalid) return false; + std::string strUserPass(userpass_data.begin(), userpass_data.end()); if (strUserPass.find(':') != std::string::npos) strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':')); diff --git a/src/i2p.cpp b/src/i2p.cpp index ccba14d63d..66f19b90d0 100644 --- a/src/i2p.cpp +++ b/src/i2p.cpp @@ -70,7 +70,7 @@ static Binary DecodeI2PBase64(const std::string& i2p_b64) { const std::string& std_b64 = SwapBase64(i2p_b64); bool invalid; - Binary decoded = DecodeBase64(std_b64.c_str(), &invalid); + Binary decoded = DecodeBase64(std_b64, &invalid); if (invalid) { throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64)); } diff --git a/src/netaddress.cpp b/src/netaddress.cpp index bc1915aad9..18f56c9bbe 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -235,7 +235,7 @@ bool CNetAddr::SetTor(const std::string& addr) } bool invalid; - const auto& input = DecodeBase32(addr.substr(0, addr.size() - suffix_len).c_str(), &invalid); + const auto& input = DecodeBase32(addr.substr(0, addr.size() - suffix_len), &invalid); if (invalid) { return false; diff --git a/src/psbt.cpp b/src/psbt.cpp index c8c73e130b..9b8f909349 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -389,17 +389,17 @@ std::string PSBTRoleName(PSBTRole role) { bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error) { bool invalid; - std::string tx_data = DecodeBase64(base64_tx, &invalid); + auto tx_data = DecodeBase64(base64_tx, &invalid); if (invalid) { error = "invalid base64"; return false; } - return DecodeRawPSBT(psbt, tx_data, error); + return DecodeRawPSBT(psbt, MakeByteSpan(tx_data), error); } -bool DecodeRawPSBT(PartiallySignedTransaction& psbt, const std::string& tx_data, std::string& error) +bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span tx_data, std::string& error) { - CDataStream ss_data(MakeByteSpan(tx_data), SER_NETWORK, PROTOCOL_VERSION); + CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION); try { ss_data >> psbt; if (!ss_data.empty()) { diff --git a/src/psbt.h b/src/psbt.h index f0ceb02481..8a9cbd33d2 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -988,6 +988,6 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti //! Decode a base64ed PSBT into a PartiallySignedTransaction [[nodiscard]] bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error); //! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction -[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error); +[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, Span raw_psbt, std::string& error); #endif // BITCOIN_PSBT_H diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 91ce420a33..663e86aa29 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -194,7 +194,7 @@ void WalletFrame::gotoVerifyMessageTab(QString addr) void WalletFrame::gotoLoadPSBT(bool from_clipboard) { - std::string data; + std::vector data; if (from_clipboard) { std::string raw = QApplication::clipboard()->text().toStdString(); @@ -214,12 +214,12 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard) return; } std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary}; - data = std::string(std::istreambuf_iterator{in}, {}); + data.assign(std::istream_iterator{in}, {}); } std::string error; PartiallySignedTransaction psbtx; - if (!DecodeRawPSBT(psbtx, data, error)) { + if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) { Q_EMIT message(tr("Error"), tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR); return; } diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 8a44e65165..2e5f6a2378 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -23,9 +23,9 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) strEnc = EncodeBase32(vstrIn[i], false); BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]); bool invalid; - std::string strDec = DecodeBase32(vstrOut[i], &invalid); + auto dec = DecodeBase32(vstrOut[i], &invalid); BOOST_CHECK(!invalid); - BOOST_CHECK_EQUAL(strDec, vstrIn[i]); + BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); } // Decoding strings with embedded NUL characters should fail diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 04b5185653..5727b09838 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -20,9 +20,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) std::string strEnc = EncodeBase64(vstrIn[i]); BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); bool invalid; - std::string strDec = DecodeBase64(strEnc, &invalid); + auto dec = DecodeBase64(strEnc, &invalid); BOOST_CHECK(!invalid); - BOOST_CHECK_EQUAL(strDec, vstrIn[i]); + BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); } { diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp index 196410e29c..0d48a140f7 100644 --- a/src/test/fuzz/base_encode_decode.cpp +++ b/src/test/fuzz/base_encode_decode.cpp @@ -37,16 +37,16 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode) } bool pf_invalid; - std::string decoded_string = DecodeBase32(random_encoded_string, &pf_invalid); + decoded = DecodeBase32(random_encoded_string, &pf_invalid); if (!pf_invalid) { - const std::string encoded_string = EncodeBase32(decoded_string); + const std::string encoded_string = EncodeBase32(decoded); assert(encoded_string == TrimString(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } - decoded_string = DecodeBase64(random_encoded_string, &pf_invalid); + decoded = DecodeBase64(random_encoded_string, &pf_invalid); if (!pf_invalid) { - const std::string encoded_string = EncodeBase64(decoded_string); + const std::string encoded_string = EncodeBase64(decoded); assert(encoded_string == TrimString(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp index 669688a80d..baa64bba0f 100644 --- a/src/test/fuzz/psbt.cpp +++ b/src/test/fuzz/psbt.cpp @@ -32,7 +32,8 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt) FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; PartiallySignedTransaction psbt_mut; std::string error; - if (!DecodeRawPSBT(psbt_mut, fuzzed_data_provider.ConsumeRandomLengthString(), error)) { + auto str = fuzzed_data_provider.ConsumeRandomLengthString(); + if (!DecodeRawPSBT(psbt_mut, MakeByteSpan(str), error)) { return; } const PartiallySignedTransaction psbt = psbt_mut; @@ -79,7 +80,8 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt) } PartiallySignedTransaction psbt_merge; - if (!DecodeRawPSBT(psbt_merge, fuzzed_data_provider.ConsumeRandomLengthString(), error)) { + str = fuzzed_data_provider.ConsumeRandomLengthString(); + if (!DecodeRawPSBT(psbt_merge, MakeByteSpan(str), error)) { psbt_merge = psbt; } psbt_mut = psbt; diff --git a/src/util/message.cpp b/src/util/message.cpp index 2c7f0406f0..a4e495c1d1 100644 --- a/src/util/message.cpp +++ b/src/util/message.cpp @@ -36,7 +36,7 @@ MessageVerificationResult MessageVerify( } bool invalid = false; - std::vector signature_bytes = DecodeBase64(signature.c_str(), &invalid); + std::vector signature_bytes = DecodeBase64(signature, &invalid); if (invalid) { return MessageVerificationResult::ERR_MALFORMED_SIGNATURE; } diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 6b6644aa9f..a861885269 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -172,14 +172,13 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) return ret; } -std::string DecodeBase64(const std::string& str, bool* pf_invalid) +std::vector DecodeBase64(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { *pf_invalid = true; return {}; } - std::vector vchRet = DecodeBase64(str.c_str(), pf_invalid); - return std::string((const char*)vchRet.data(), vchRet.size()); + return DecodeBase64(str.c_str(), pf_invalid); } std::string EncodeBase32(Span input, bool pad) @@ -248,14 +247,13 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) return ret; } -std::string DecodeBase32(const std::string& str, bool* pf_invalid) +std::vector DecodeBase32(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { *pf_invalid = true; return {}; } - std::vector vchRet = DecodeBase32(str.c_str(), pf_invalid); - return std::string((const char*)vchRet.data(), vchRet.size()); + return DecodeBase32(str.c_str(), pf_invalid); } namespace { diff --git a/src/util/strencodings.h b/src/util/strencodings.h index c87b2d2415..5d85f0580b 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -65,12 +65,12 @@ bool IsHex(std::string_view str); */ bool IsHexNumber(std::string_view str); std::vector DecodeBase64(const char* p, bool* pf_invalid); -std::string DecodeBase64(const std::string& str, bool* pf_invalid); +std::vector DecodeBase64(const std::string& str, bool* pf_invalid); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } std::vector DecodeBase32(const char* p, bool* pf_invalid); -std::string DecodeBase32(const std::string& str, bool* pf_invalid); +std::vector DecodeBase32(const std::string& str, bool* pf_invalid); /** * Base32 encode. -- cgit v1.2.3 From 78f3ac51b7d073d12da6a3b9b7d80d91e04ce3a7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 13:52:06 -0400 Subject: Make DecodeBase{32,64} return optional instead of taking bool* --- src/httprpc.cpp | 8 ++++---- src/i2p.cpp | 7 +++---- src/netaddress.cpp | 20 +++++++++----------- src/psbt.cpp | 7 +++---- src/qt/walletframe.cpp | 6 +++--- src/test/base32_tests.cpp | 20 +++++++------------- src/test/base64_tests.cpp | 20 +++++++------------- src/test/fuzz/base_encode_decode.cpp | 13 ++++++------- src/util/message.cpp | 7 +++---- src/util/strencodings.cpp | 18 ++++++++---------- src/util/strencodings.h | 8 ++++---- 11 files changed, 57 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 96cccd8de9..b9041227be 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -132,10 +132,10 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna if (strAuth.substr(0, 6) != "Basic ") return false; std::string strUserPass64 = TrimString(strAuth.substr(6)); - bool invalid; - std::vector userpass_data = DecodeBase64(strUserPass64, &invalid); - if (invalid) return false; - std::string strUserPass(userpass_data.begin(), userpass_data.end()); + auto userpass_data = DecodeBase64(strUserPass64); + std::string strUserPass; + if (!userpass_data) return false; + strUserPass.assign(userpass_data->begin(), userpass_data->end()); if (strUserPass.find(':') != std::string::npos) strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':')); diff --git a/src/i2p.cpp b/src/i2p.cpp index 66f19b90d0..e08b5461fe 100644 --- a/src/i2p.cpp +++ b/src/i2p.cpp @@ -69,12 +69,11 @@ static std::string SwapBase64(const std::string& from) static Binary DecodeI2PBase64(const std::string& i2p_b64) { const std::string& std_b64 = SwapBase64(i2p_b64); - bool invalid; - Binary decoded = DecodeBase64(std_b64, &invalid); - if (invalid) { + auto decoded = DecodeBase64(std_b64); + if (!decoded) { throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64)); } - return decoded; + return std::move(*decoded); } /** diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 18f56c9bbe..7943eaf257 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -234,17 +234,16 @@ bool CNetAddr::SetTor(const std::string& addr) return false; } - bool invalid; - const auto& input = DecodeBase32(addr.substr(0, addr.size() - suffix_len), &invalid); + auto input = DecodeBase32(addr.substr(0, addr.size() - suffix_len)); - if (invalid) { + if (!input) { return false; } - if (input.size() == torv3::TOTAL_LEN) { - Span input_pubkey{input.data(), ADDR_TORV3_SIZE}; - Span input_checksum{input.data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN}; - Span input_version{input.data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)}; + if (input->size() == torv3::TOTAL_LEN) { + Span input_pubkey{input->data(), ADDR_TORV3_SIZE}; + Span input_checksum{input->data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN}; + Span input_version{input->data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)}; if (input_version != torv3::VERSION) { return false; @@ -280,15 +279,14 @@ bool CNetAddr::SetI2P(const std::string& addr) // can decode it. const std::string b32_padded = addr.substr(0, b32_len) + "===="; - bool invalid; - const auto& address_bytes = DecodeBase32(b32_padded.c_str(), &invalid); + auto address_bytes = DecodeBase32(b32_padded); - if (invalid || address_bytes.size() != ADDR_I2P_SIZE) { + if (!address_bytes || address_bytes->size() != ADDR_I2P_SIZE) { return false; } m_net = NET_I2P; - m_addr.assign(address_bytes.begin(), address_bytes.end()); + m_addr.assign(address_bytes->begin(), address_bytes->end()); return true; } diff --git a/src/psbt.cpp b/src/psbt.cpp index 9b8f909349..6465e353be 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -388,13 +388,12 @@ std::string PSBTRoleName(PSBTRole role) { bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error) { - bool invalid; - auto tx_data = DecodeBase64(base64_tx, &invalid); - if (invalid) { + auto tx_data = DecodeBase64(base64_tx); + if (!tx_data) { error = "invalid base64"; return false; } - return DecodeRawPSBT(psbt, MakeByteSpan(tx_data), error); + return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error); } bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span tx_data, std::string& error) diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 663e86aa29..dc4e25a02b 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -198,12 +198,12 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard) if (from_clipboard) { std::string raw = QApplication::clipboard()->text().toStdString(); - bool invalid; - data = DecodeBase64(raw, &invalid); - if (invalid) { + auto result = DecodeBase64(raw); + if (!result) { Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR); return; } + data = std::move(*result); } else { QString filename = GUIUtil::getOpenFileName(this, tr("Load Transaction Data"), QString(), diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 2e5f6a2378..c6109dfeb0 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -22,22 +22,16 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); strEnc = EncodeBase32(vstrIn[i], false); BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]); - bool invalid; - auto dec = DecodeBase32(vstrOut[i], &invalid); - BOOST_CHECK(!invalid); - BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); + auto dec = DecodeBase32(vstrOut[i]); + BOOST_REQUIRE(dec); + BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); } // Decoding strings with embedded NUL characters should fail - bool failure; - (void)DecodeBase32("invalid\0"s, &failure); // correct size, invalid due to \0 - BOOST_CHECK(failure); - (void)DecodeBase32("AWSX3VPP"s, &failure); // valid - BOOST_CHECK(!failure); - (void)DecodeBase32("AWSX3VPP\0invalid"s, &failure); // correct size, invalid due to \0 - BOOST_CHECK(failure); - (void)DecodeBase32("AWSX3VPPinvalid"s, &failure); // invalid size - BOOST_CHECK(failure); + BOOST_CHECK(!DecodeBase32("invalid\0"s)); // correct size, invalid due to \0 + BOOST_CHECK(DecodeBase32("AWSX3VPP"s)); // valid + BOOST_CHECK(!DecodeBase32("AWSX3VPP\0invalid"s)); // correct size, invalid due to \0 + BOOST_CHECK(!DecodeBase32("AWSX3VPPinvalid"s)); // invalid size } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 5727b09838..54a02c6bf8 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -19,10 +19,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) { std::string strEnc = EncodeBase64(vstrIn[i]); BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); - bool invalid; - auto dec = DecodeBase64(strEnc, &invalid); - BOOST_CHECK(!invalid); - BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); + auto dec = DecodeBase64(strEnc); + BOOST_REQUIRE(dec); + BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]); } { @@ -36,15 +35,10 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) } // Decoding strings with embedded NUL characters should fail - bool failure; - (void)DecodeBase64("invalid\0"s, &failure); - BOOST_CHECK(failure); - (void)DecodeBase64("nQB/pZw="s, &failure); - BOOST_CHECK(!failure); - (void)DecodeBase64("nQB/pZw=\0invalid"s, &failure); - BOOST_CHECK(failure); - (void)DecodeBase64("nQB/pZw=invalid\0"s, &failure); - BOOST_CHECK(failure); + BOOST_CHECK(!DecodeBase64("invalid\0"s)); + BOOST_CHECK(DecodeBase64("nQB/pZw="s)); + BOOST_CHECK(!DecodeBase64("nQB/pZw=\0invalid"s)); + BOOST_CHECK(!DecodeBase64("nQB/pZw=invalid\0"s)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp index 0d48a140f7..11dd820e4f 100644 --- a/src/test/fuzz/base_encode_decode.cpp +++ b/src/test/fuzz/base_encode_decode.cpp @@ -36,17 +36,16 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode) assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } - bool pf_invalid; - decoded = DecodeBase32(random_encoded_string, &pf_invalid); - if (!pf_invalid) { - const std::string encoded_string = EncodeBase32(decoded); + auto result = DecodeBase32(random_encoded_string); + if (result) { + const std::string encoded_string = EncodeBase32(*result); assert(encoded_string == TrimString(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } - decoded = DecodeBase64(random_encoded_string, &pf_invalid); - if (!pf_invalid) { - const std::string encoded_string = EncodeBase64(decoded); + result = DecodeBase64(random_encoded_string); + if (result) { + const std::string encoded_string = EncodeBase64(*result); assert(encoded_string == TrimString(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } diff --git a/src/util/message.cpp b/src/util/message.cpp index a4e495c1d1..f58876f915 100644 --- a/src/util/message.cpp +++ b/src/util/message.cpp @@ -35,14 +35,13 @@ MessageVerificationResult MessageVerify( return MessageVerificationResult::ERR_ADDRESS_NO_KEY; } - bool invalid = false; - std::vector signature_bytes = DecodeBase64(signature, &invalid); - if (invalid) { + auto signature_bytes = DecodeBase64(signature); + if (!signature_bytes) { return MessageVerificationResult::ERR_MALFORMED_SIGNATURE; } CPubKey pubkey; - if (!pubkey.RecoverCompact(MessageHash(message), signature_bytes)) { + if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) { return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED; } diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index a861885269..c7c9870a02 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -126,7 +126,7 @@ std::string EncodeBase64(Span input) return str; } -std::vector DecodeBase64(const char* p, bool* pf_invalid) +std::optional> DecodeBase64(const char* p) { static const int8_t decode64_table[256]{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -167,18 +167,17 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 4 == 0 && p - q < 4; - *pf_invalid = !valid; + if (!valid) return {}; return ret; } -std::vector DecodeBase64(const std::string& str, bool* pf_invalid) +std::optional> DecodeBase64(const std::string& str) { if (!ValidAsCString(str)) { - *pf_invalid = true; return {}; } - return DecodeBase64(str.c_str(), pf_invalid); + return DecodeBase64(str.c_str()); } std::string EncodeBase32(Span input, bool pad) @@ -201,7 +200,7 @@ std::string EncodeBase32(const std::string& str, bool pad) return EncodeBase32(MakeUCharSpan(str), pad); } -std::vector DecodeBase32(const char* p, bool* pf_invalid) +std::optional> DecodeBase32(const char* p) { static const int8_t decode32_table[256]{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -242,18 +241,17 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 8 == 0 && p - q < 8; - *pf_invalid = !valid; + if (!valid) return {}; return ret; } -std::vector DecodeBase32(const std::string& str, bool* pf_invalid) +std::optional> DecodeBase32(const std::string& str) { if (!ValidAsCString(str)) { - *pf_invalid = true; return {}; } - return DecodeBase32(str.c_str(), pf_invalid); + return DecodeBase32(str.c_str()); } namespace { diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 5d85f0580b..27f6ec6e00 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -64,13 +64,13 @@ bool IsHex(std::string_view str); * Return true if the string is a hex number, optionally prefixed with "0x" */ bool IsHexNumber(std::string_view str); -std::vector DecodeBase64(const char* p, bool* pf_invalid); -std::vector DecodeBase64(const std::string& str, bool* pf_invalid); +std::optional> DecodeBase64(const char* p); +std::optional> DecodeBase64(const std::string& str); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } -std::vector DecodeBase32(const char* p, bool* pf_invalid); -std::vector DecodeBase32(const std::string& str, bool* pf_invalid); +std::optional> DecodeBase32(const char* p); +std::optional> DecodeBase32(const std::string& str); /** * Base32 encode. -- cgit v1.2.3 From 1a72d62152bfdd7c5c2b2704b679f894e7d35e37 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 11:58:54 -0400 Subject: Generalize ConvertBits to permit transforming the input --- src/util/strencodings.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 27f6ec6e00..8a277bac4a 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -249,15 +249,26 @@ bool TimingResistantEqual(const T& a, const T& b) */ [[nodiscard]] bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); +namespace { +/** Helper class for the default infn argument to ConvertBits (just returns the input). */ +struct IntIdentity +{ + [[maybe_unused]] int operator()(int x) const { return x; } +}; + +} // namespace + /** Convert from one power-of-2 number base to another. */ -template -bool ConvertBits(const O& outfn, I it, I end) { +template +bool ConvertBits(O outfn, It it, It end, I infn = {}) { size_t acc = 0; size_t bits = 0; constexpr size_t maxv = (1 << tobits) - 1; constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1; while (it != end) { - acc = ((acc << frombits) | *it) & max_acc; + int v = infn(*it); + if (v < 0) return false; + acc = ((acc << frombits) | v) & max_acc; bits += frombits; while (bits >= tobits) { bits -= tobits; -- cgit v1.2.3 From 8ffbd1412d887535ce5eb613884858c319bd12be Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 14:10:10 -0400 Subject: Make DecodeBase{32,64} take string_view arguments --- src/netaddress.cpp | 2 +- src/util/strencodings.cpp | 85 ++++++++++++++--------------------------------- src/util/strencodings.h | 6 ++-- 3 files changed, 28 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 7943eaf257..774a6fb254 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -234,7 +234,7 @@ bool CNetAddr::SetTor(const std::string& addr) return false; } - auto input = DecodeBase32(addr.substr(0, addr.size() - suffix_len)); + auto input = DecodeBase32(std::string_view{addr}.substr(0, addr.size() - suffix_len)); if (!input) { return false; diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index c7c9870a02..b5e662cf66 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -126,7 +126,7 @@ std::string EncodeBase64(Span input) return str; } -std::optional> DecodeBase64(const char* p) +std::optional> DecodeBase64(std::string_view str) { static const int8_t decode64_table[256]{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -144,42 +144,23 @@ std::optional> DecodeBase64(const char* p) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - const char* e = p; - std::vector val; - val.reserve(strlen(p)); - while (*p != 0) { - int x = decode64_table[(unsigned char)*p]; - if (x == -1) break; - val.push_back(uint8_t(x)); - ++p; - } + if (str.size() % 4 != 0) return {}; + /* One or two = characters at the end are permitted. */ + if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1); + if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1); std::vector ret; - ret.reserve((val.size() * 3) / 4); - bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end()); - - const char* q = p; - while (valid && *p != 0) { - if (*p != '=') { - valid = false; - break; - } - ++p; - } - valid = valid && (p - e) % 4 == 0 && p - q < 4; + ret.reserve((str.size() * 3) / 4); + bool valid = ConvertBits<6, 8, false>( + [&](unsigned char c) { ret.push_back(c); }, + str.begin(), str.end(), + [](char c) { return decode64_table[uint8_t(c)]; } + ); if (!valid) return {}; return ret; } -std::optional> DecodeBase64(const std::string& str) -{ - if (!ValidAsCString(str)) { - return {}; - } - return DecodeBase64(str.c_str()); -} - std::string EncodeBase32(Span input, bool pad) { static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; @@ -200,7 +181,7 @@ std::string EncodeBase32(const std::string& str, bool pad) return EncodeBase32(MakeUCharSpan(str), pad); } -std::optional> DecodeBase32(const char* p) +std::optional> DecodeBase32(std::string_view str) { static const int8_t decode32_table[256]{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -218,42 +199,26 @@ std::optional> DecodeBase32(const char* p) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - const char* e = p; - std::vector val; - val.reserve(strlen(p)); - while (*p != 0) { - int x = decode32_table[(unsigned char)*p]; - if (x == -1) break; - val.push_back(uint8_t(x)); - ++p; - } + if (str.size() % 8 != 0) return {}; + /* 1, 3, 4, or 6 padding '=' suffix characters are permitted. */ + if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1); + if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2); + if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1); + if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2); std::vector ret; - ret.reserve((val.size() * 5) / 8); - bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end()); - - const char* q = p; - while (valid && *p != 0) { - if (*p != '=') { - valid = false; - break; - } - ++p; - } - valid = valid && (p - e) % 8 == 0 && p - q < 8; + ret.reserve((str.size() * 5) / 8); + bool valid = ConvertBits<5, 8, false>( + [&](unsigned char c) { ret.push_back(c); }, + str.begin(), str.end(), + [](char c) { return decode32_table[uint8_t(c)]; } + ); + if (!valid) return {}; return ret; } -std::optional> DecodeBase32(const std::string& str) -{ - if (!ValidAsCString(str)) { - return {}; - } - return DecodeBase32(str.c_str()); -} - namespace { template bool ParseIntegral(const std::string& str, T* out) diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 8a277bac4a..ba8132b08d 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -64,13 +64,11 @@ bool IsHex(std::string_view str); * Return true if the string is a hex number, optionally prefixed with "0x" */ bool IsHexNumber(std::string_view str); -std::optional> DecodeBase64(const char* p); -std::optional> DecodeBase64(const std::string& str); +std::optional> DecodeBase64(std::string_view str); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } -std::optional> DecodeBase32(const char* p); -std::optional> DecodeBase32(const std::string& str); +std::optional> DecodeBase32(std::string_view str); /** * Base32 encode. -- cgit v1.2.3 From e7d2fbda63c346ae88767c3f8d4db3edeae2dc0b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2022 15:05:47 -0400 Subject: Use std::string_view throughout util strencodings/string --- src/bitcoin-tx.cpp | 2 +- src/httprpc.cpp | 2 +- src/test/fuzz/base_encode_decode.cpp | 4 ++-- src/test/fuzz/http_request.cpp | 2 +- src/test/util_tests.cpp | 20 ++++++++++---------- src/util/strencodings.cpp | 28 ++++++++++++++-------------- src/util/strencodings.h | 34 +++++++++++++++++----------------- src/util/string.h | 29 +++++++++++++++++++++-------- src/util/system.cpp | 4 ++-- 9 files changed, 69 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 05f910e9cb..cdc5960c12 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -240,7 +240,7 @@ static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInId template static T TrimAndParse(const std::string& int_str, const std::string& err) { - const auto parsed{ToIntegral(TrimString(int_str))}; + const auto parsed{ToIntegral(TrimStringView(int_str))}; if (!parsed.has_value()) { throw std::runtime_error(err + " '" + int_str + "'"); } diff --git a/src/httprpc.cpp b/src/httprpc.cpp index b9041227be..93d9acf5da 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -131,7 +131,7 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna return false; if (strAuth.substr(0, 6) != "Basic ") return false; - std::string strUserPass64 = TrimString(strAuth.substr(6)); + std::string_view strUserPass64 = TrimStringView(std::string_view{strAuth}.substr(6)); auto userpass_data = DecodeBase64(strUserPass64); std::string strUserPass; if (!userpass_data) return false; diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp index 11dd820e4f..48356065b0 100644 --- a/src/test/fuzz/base_encode_decode.cpp +++ b/src/test/fuzz/base_encode_decode.cpp @@ -26,7 +26,7 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode) std::vector decoded; if (DecodeBase58(random_encoded_string, decoded, 100)) { const std::string encoded_string = EncodeBase58(decoded); - assert(encoded_string == TrimString(encoded_string)); + assert(encoded_string == TrimStringView(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } @@ -39,7 +39,7 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode) auto result = DecodeBase32(random_encoded_string); if (result) { const std::string encoded_string = EncodeBase32(*result); - assert(encoded_string == TrimString(encoded_string)); + assert(encoded_string == TrimStringView(encoded_string)); assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string))); } diff --git a/src/test/fuzz/http_request.cpp b/src/test/fuzz/http_request.cpp index 916e90e986..0fe18abaa9 100644 --- a/src/test/fuzz/http_request.cpp +++ b/src/test/fuzz/http_request.cpp @@ -39,7 +39,7 @@ FUZZ_TARGET(http_request) // and is a consequence of our hacky but necessary use of the internal function evhttp_parse_firstline_ in // this fuzzing harness. The workaround is not aesthetically pleasing, but it successfully avoids the troublesome // code path. " http:// HTTP/1.1\n" was a crashing input prior to this workaround. - const std::string http_buffer_str = ToLower({http_buffer.begin(), http_buffer.end()}); + const std::string http_buffer_str = ToLower(std::string{http_buffer.begin(), http_buffer.end()}); if (http_buffer_str.find(" http://") != std::string::npos || http_buffer_str.find(" https://") != std::string::npos || evhttp_parse_firstline_(evreq, evbuf) != 1 || evhttp_parse_headers_(evreq, evbuf) != 1) { evbuffer_free(evbuf); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 779ed20032..1ca20fd848 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -226,17 +226,17 @@ BOOST_AUTO_TEST_CASE(util_Join) BOOST_AUTO_TEST_CASE(util_TrimString) { BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar"); - BOOST_CHECK_EQUAL(TrimString("\t \n \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar"); + BOOST_CHECK_EQUAL(TrimStringView("\t \n \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar"); BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar"); - BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n "); + BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n "); BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar"); - BOOST_CHECK_EQUAL(TrimString("foo bar", "fobar"), " "); + BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " "); BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7)); - BOOST_CHECK_EQUAL(TrimString(std::string(" foo ", 5)), std::string("foo", 3)); + BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3)); BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2)); - BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6)); + BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6)); BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01", 5)), std::string("\0", 1)); - BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), ""); + BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), ""); } BOOST_AUTO_TEST_CASE(util_FormatParseISO8601DateTime) @@ -2618,13 +2618,13 @@ BOOST_AUTO_TEST_CASE(message_hash) BOOST_AUTO_TEST_CASE(remove_prefix) { BOOST_CHECK_EQUAL(RemovePrefix("./util/system.h", "./"), "util/system.h"); - BOOST_CHECK_EQUAL(RemovePrefix("foo", "foo"), ""); + BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), ""); BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o"); - BOOST_CHECK_EQUAL(RemovePrefix("foo", "f"), "oo"); + BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo"); BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo"); - BOOST_CHECK_EQUAL(RemovePrefix("fo", "foo"), "fo"); + BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo"); BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f"); - BOOST_CHECK_EQUAL(RemovePrefix("", "foo"), ""); + BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), ""); BOOST_CHECK_EQUAL(RemovePrefix("", ""), ""); } diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index b5e662cf66..35f62f0422 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -94,7 +94,7 @@ std::vector ParseHex(std::string_view str) return vch; } -void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut) +void SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut) { size_t colon = in.find_last_of(':'); // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator @@ -176,7 +176,7 @@ std::string EncodeBase32(Span input, bool pad) return str; } -std::string EncodeBase32(const std::string& str, bool pad) +std::string EncodeBase32(std::string_view str, bool pad) { return EncodeBase32(MakeUCharSpan(str), pad); } @@ -221,7 +221,7 @@ std::optional> DecodeBase32(std::string_view str) namespace { template -bool ParseIntegral(const std::string& str, T* out) +bool ParseIntegral(std::string_view str, T* out) { static_assert(std::is_integral::value); // Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when @@ -240,37 +240,37 @@ bool ParseIntegral(const std::string& str, T* out) } }; // namespace -bool ParseInt32(const std::string& str, int32_t* out) +bool ParseInt32(std::string_view str, int32_t* out) { return ParseIntegral(str, out); } -bool ParseInt64(const std::string& str, int64_t* out) +bool ParseInt64(std::string_view str, int64_t* out) { return ParseIntegral(str, out); } -bool ParseUInt8(const std::string& str, uint8_t* out) +bool ParseUInt8(std::string_view str, uint8_t* out) { return ParseIntegral(str, out); } -bool ParseUInt16(const std::string& str, uint16_t* out) +bool ParseUInt16(std::string_view str, uint16_t* out) { return ParseIntegral(str, out); } -bool ParseUInt32(const std::string& str, uint32_t* out) +bool ParseUInt32(std::string_view str, uint32_t* out) { return ParseIntegral(str, out); } -bool ParseUInt64(const std::string& str, uint64_t* out) +bool ParseUInt64(std::string_view str, uint64_t* out) { return ParseIntegral(str, out); } -std::string FormatParagraph(const std::string& in, size_t width, size_t indent) +std::string FormatParagraph(std::string_view in, size_t width, size_t indent) { assert(width >= indent); std::stringstream out; @@ -339,7 +339,7 @@ static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantiss return true; } -bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) +bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out) { int64_t mantissa = 0; int64_t exponent = 0; @@ -431,14 +431,14 @@ bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) return true; } -std::string ToLower(const std::string& str) +std::string ToLower(std::string_view str) { std::string r; for (auto ch : str) r += ToLower(ch); return r; } -std::string ToUpper(const std::string& str) +std::string ToUpper(std::string_view str) { std::string r; for (auto ch : str) r += ToUpper(ch); @@ -466,7 +466,7 @@ std::string HexStr(const Span s) return rv; } -std::optional ParseByteUnits(const std::string& str, ByteUnit default_multiplier) +std::optional ParseByteUnits(std::string_view str, ByteUnit default_multiplier) { if (str.empty()) { return std::nullopt; diff --git a/src/util/strencodings.h b/src/util/strencodings.h index ba8132b08d..ebb6d88952 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -67,7 +67,7 @@ bool IsHexNumber(std::string_view str); std::optional> DecodeBase64(std::string_view str); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } -inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } +inline std::string EncodeBase64(std::string_view str) { return EncodeBase64(MakeUCharSpan(str)); } std::optional> DecodeBase32(std::string_view str); /** @@ -82,9 +82,9 @@ std::string EncodeBase32(Span input, bool pad = true); * If `pad` is true, then the output will be padded with '=' so that its length * is a multiple of 8. */ -std::string EncodeBase32(const std::string& str, bool pad = true); +std::string EncodeBase32(std::string_view str, bool pad = true); -void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut); +void SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut); // LocaleIndependentAtoi is provided for backwards compatibility reasons. // @@ -98,12 +98,12 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut); // undefined behavior, while this function returns the maximum or minimum // values, respectively. template -T LocaleIndependentAtoi(const std::string& str) +T LocaleIndependentAtoi(std::string_view str) { static_assert(std::is_integral::value); T result; // Emulate atoi(...) handling of white space and leading +/-. - std::string s = TrimString(str); + std::string_view s = TrimStringView(str); if (!s.empty() && s[0] == '+') { if (s.length() >= 2 && s[1] == '-') { return 0; @@ -159,7 +159,7 @@ constexpr inline bool IsSpace(char c) noexcept { * parsed value is not in the range representable by the type T. */ template -std::optional ToIntegral(const std::string& str) +std::optional ToIntegral(std::string_view str) { static_assert(std::is_integral::value); T result; @@ -175,42 +175,42 @@ std::optional ToIntegral(const std::string& str) * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -[[nodiscard]] bool ParseInt32(const std::string& str, int32_t *out); +[[nodiscard]] bool ParseInt32(std::string_view str, int32_t *out); /** * Convert string to signed 64-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -[[nodiscard]] bool ParseInt64(const std::string& str, int64_t *out); +[[nodiscard]] bool ParseInt64(std::string_view str, int64_t *out); /** * Convert decimal string to unsigned 8-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -[[nodiscard]] bool ParseUInt8(const std::string& str, uint8_t *out); +[[nodiscard]] bool ParseUInt8(std::string_view str, uint8_t *out); /** * Convert decimal string to unsigned 16-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if the entire string could not be parsed or if overflow or underflow occurred. */ -[[nodiscard]] bool ParseUInt16(const std::string& str, uint16_t* out); +[[nodiscard]] bool ParseUInt16(std::string_view str, uint16_t* out); /** * Convert decimal string to unsigned 32-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -[[nodiscard]] bool ParseUInt32(const std::string& str, uint32_t *out); +[[nodiscard]] bool ParseUInt32(std::string_view str, uint32_t *out); /** * Convert decimal string to unsigned 64-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. */ -[[nodiscard]] bool ParseUInt64(const std::string& str, uint64_t *out); +[[nodiscard]] bool ParseUInt64(std::string_view str, uint64_t *out); /** * Convert a span of bytes to a lower-case hexadecimal string. @@ -223,7 +223,7 @@ inline std::string HexStr(const Span s) { return HexStr(MakeUCh * Format a paragraph of text to a fixed width, adding spaces for * indentation to any added line. */ -std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0); +std::string FormatParagraph(std::string_view in, size_t width = 79, size_t indent = 0); /** * Timing-attack-resistant comparison. @@ -245,7 +245,7 @@ bool TimingResistantEqual(const T& a, const T& b) * @returns true on success, false on error. * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. */ -[[nodiscard]] bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); +[[nodiscard]] bool ParseFixedPoint(std::string_view, int decimals, int64_t *amount_out); namespace { /** Helper class for the default infn argument to ConvertBits (just returns the input). */ @@ -306,7 +306,7 @@ constexpr char ToLower(char c) * @param[in] str the string to convert to lowercase. * @returns lowercased equivalent of str */ -std::string ToLower(const std::string& str); +std::string ToLower(std::string_view str); /** * Converts the given character to its uppercase equivalent. @@ -332,7 +332,7 @@ constexpr char ToUpper(char c) * @param[in] str the string to convert to uppercase. * @returns UPPERCASED EQUIVALENT OF str */ -std::string ToUpper(const std::string& str); +std::string ToUpper(std::string_view str); /** * Capitalizes the first character of the given string. @@ -356,6 +356,6 @@ std::string Capitalize(std::string str); * @returns optional uint64_t bytes from str or nullopt * if ToIntegral is false, str is empty, trailing whitespace or overflow */ -std::optional ParseByteUnits(const std::string& str, ByteUnit default_multiplier); +std::optional ParseByteUnits(std::string_view str, ByteUnit default_multiplier); #endif // BITCOIN_UTIL_STRENCODINGS_H diff --git a/src/util/string.h b/src/util/string.h index bcd6905fd5..81f5e21111 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -21,17 +21,22 @@ return spanparsing::Split(str, sep); } -[[nodiscard]] inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v") +[[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v") { std::string::size_type front = str.find_first_not_of(pattern); if (front == std::string::npos) { - return std::string(); + return {}; } std::string::size_type end = str.find_last_not_of(pattern); return str.substr(front, end - front + 1); } -[[nodiscard]] inline std::string RemovePrefix(const std::string& str, const std::string& prefix) +[[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v") +{ + return std::string(TrimStringView(str, pattern)); +} + +[[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix) { if (str.substr(0, prefix.size()) == prefix) { return str.substr(prefix.size()); @@ -39,6 +44,11 @@ return str; } +[[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix) +{ + return std::string(RemovePrefixView(str, prefix)); +} + /** * Join a list of items * @@ -58,14 +68,14 @@ auto Join(const std::vector& list, const BaseType& separator, UnaryOp unary_o return ret; } -template -T Join(const std::vector& list, const T& separator) +template +T Join(const std::vector& list, const T2& separator) { return Join(list, separator, [](const T& i) { return i; }); } // Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above. -inline std::string Join(const std::vector& list, const std::string& separator) +inline std::string Join(const std::vector& list, std::string_view separator) { return Join(list, separator); } @@ -81,9 +91,12 @@ inline std::string MakeUnorderedList(const std::vector& items) /** * Check if a string does not contain any embedded NUL (\0) characters */ -[[nodiscard]] inline bool ValidAsCString(const std::string& str) noexcept +[[nodiscard]] inline bool ValidAsCString(std::string_view str) noexcept { - return str.size() == strlen(str.c_str()); + for (auto c : str) { + if (c == 0) return false; + } + return true; } /** diff --git a/src/util/system.cpp b/src/util/system.cpp index a7e66defcd..f9a9ad3e20 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -853,8 +853,8 @@ static bool GetConfigOptions(std::istream& stream, const std::string& filepath, error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str); return false; } else if ((pos = str.find('=')) != std::string::npos) { - std::string name = prefix + TrimString(str.substr(0, pos), pattern); - std::string value = TrimString(str.substr(pos + 1), pattern); + std::string name = prefix + TrimString(std::string_view{str}.substr(0, pos), pattern); + std::string_view value = TrimStringView(std::string_view{str}.substr(pos + 1), pattern); if (used_hash && name.find("rpcpassword") != std::string::npos) { error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr); return false; -- cgit v1.2.3 From fa7078d84fc2858a466bc1a85404f821df682538 Mon Sep 17 00:00:00 2001 From: MacroFake Date: Wed, 27 Apr 2022 14:23:29 +0200 Subject: scripted-diff: Rename ValidAsCString to ContainsNoNUL -BEGIN VERIFY SCRIPT- sed -i 's,ValidAsCString,ContainsNoNUL,g' $(git grep -l ValidAsCString) -END VERIFY SCRIPT- --- src/base58.cpp | 4 ++-- src/netaddress.cpp | 2 +- src/netbase.cpp | 14 +++++++------- src/test/fuzz/string.cpp | 4 ++-- src/util/moneystr.cpp | 2 +- src/util/string.h | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/base58.cpp b/src/base58.cpp index dfa2e8db55..11c1ce7397 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -126,7 +126,7 @@ std::string EncodeBase58(Span input) bool DecodeBase58(const std::string& str, std::vector& vchRet, int max_ret_len) { - if (!ValidAsCString(str)) { + if (!ContainsNoNUL(str)) { return false; } return DecodeBase58(str.c_str(), vchRet, max_ret_len); @@ -160,7 +160,7 @@ std::string EncodeBase58Check(Span input) bool DecodeBase58Check(const std::string& str, std::vector& vchRet, int max_ret) { - if (!ValidAsCString(str)) { + if (!ContainsNoNUL(str)) { return false; } return DecodeBase58Check(str.c_str(), vchRet, max_ret); diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 774a6fb254..7bf11a3e48 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -210,7 +210,7 @@ static void Checksum(Span addr_pubkey, uint8_t (&checksum)[CHECKS bool CNetAddr::SetSpecial(const std::string& addr) { - if (!ValidAsCString(addr)) { + if (!ContainsNoNUL(addr)) { return false; } diff --git a/src/netbase.cpp b/src/netbase.cpp index ce23f7e4ad..8ff3b7a68c 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -136,7 +136,7 @@ static bool LookupIntern(const std::string& name, std::vector& vIP, un { vIP.clear(); - if (!ValidAsCString(name)) { + if (!ContainsNoNUL(name)) { return false; } @@ -169,7 +169,7 @@ static bool LookupIntern(const std::string& name, std::vector& vIP, un bool LookupHost(const std::string& name, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function) { - if (!ValidAsCString(name)) { + if (!ContainsNoNUL(name)) { return false; } std::string strHost = name; @@ -184,7 +184,7 @@ bool LookupHost(const std::string& name, std::vector& vIP, unsigned in bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function) { - if (!ValidAsCString(name)) { + if (!ContainsNoNUL(name)) { return false; } std::vector vIP; @@ -197,7 +197,7 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL bool Lookup(const std::string& name, std::vector& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function) { - if (name.empty() || !ValidAsCString(name)) { + if (name.empty() || !ContainsNoNUL(name)) { return false; } uint16_t port{portDefault}; @@ -216,7 +216,7 @@ bool Lookup(const std::string& name, std::vector& vAddr, uint16_t port bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function) { - if (!ValidAsCString(name)) { + if (!ContainsNoNUL(name)) { return false; } std::vector vService; @@ -229,7 +229,7 @@ bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function) { - if (!ValidAsCString(name)) { + if (!ContainsNoNUL(name)) { return {}; } CService addr; @@ -684,7 +684,7 @@ bool ConnectThroughProxy(const Proxy& proxy, const std::string& strDest, uint16_ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out) { - if (!ValidAsCString(subnet_str)) { + if (!ContainsNoNUL(subnet_str)) { return false; } diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp index b4876d427f..e6064d19b6 100644 --- a/src/test/fuzz/string.cpp +++ b/src/test/fuzz/string.cpp @@ -42,7 +42,7 @@ bool LegacyParsePrechecks(const std::string& str) return false; if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size() - 1]))) // No padding allowed return false; - if (!ValidAsCString(str)) // No embedded NUL characters allowed + if (!ContainsNoNUL(str)) // No embedded NUL characters allowed return false; return true; } @@ -188,7 +188,7 @@ FUZZ_TARGET(string) (void)TrimString(random_string_1); (void)TrimString(random_string_1, random_string_2); (void)urlDecode(random_string_1); - (void)ValidAsCString(random_string_1); + (void)ContainsNoNUL(random_string_1); (void)_(random_string_1.c_str()); try { throw scriptnum_error{random_string_1}; diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp index 2cd7a426f8..8c4bc6e6f4 100644 --- a/src/util/moneystr.cpp +++ b/src/util/moneystr.cpp @@ -40,7 +40,7 @@ std::string FormatMoney(const CAmount n) std::optional ParseMoney(const std::string& money_string) { - if (!ValidAsCString(money_string)) { + if (!ContainsNoNUL(money_string)) { return std::nullopt; } const std::string str = TrimString(money_string); diff --git a/src/util/string.h b/src/util/string.h index 81f5e21111..36b9787db4 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -91,7 +91,7 @@ inline std::string MakeUnorderedList(const std::vector& items) /** * Check if a string does not contain any embedded NUL (\0) characters */ -[[nodiscard]] inline bool ValidAsCString(std::string_view str) noexcept +[[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept { for (auto c : str) { if (c == 0) return false; -- cgit v1.2.3