diff options
author | Pieter Wuille <pieter@wuille.net> | 2022-04-04 14:10:10 -0400 |
---|---|---|
committer | MacroFake <falke.marco@gmail.com> | 2022-04-27 14:12:55 +0200 |
commit | 8ffbd1412d887535ce5eb613884858c319bd12be (patch) | |
tree | b5389e1e788d87fc12edcd7dfe94fbad3b87647e | |
parent | 1a72d62152bfdd7c5c2b2704b679f894e7d35e37 (diff) |
Make DecodeBase{32,64} take string_view arguments
-rw-r--r-- | src/netaddress.cpp | 2 | ||||
-rw-r--r-- | src/util/strencodings.cpp | 85 | ||||
-rw-r--r-- | src/util/strencodings.h | 6 |
3 files changed, 28 insertions, 65 deletions
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<const unsigned char> input) return str; } -std::optional<std::vector<unsigned char>> DecodeBase64(const char* p) +std::optional<std::vector<unsigned char>> 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<std::vector<unsigned char>> 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<uint8_t> 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<unsigned char> 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<std::vector<unsigned char>> DecodeBase64(const std::string& str) -{ - if (!ValidAsCString(str)) { - return {}; - } - return DecodeBase64(str.c_str()); -} - std::string EncodeBase32(Span<const unsigned char> 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<std::vector<unsigned char>> DecodeBase32(const char* p) +std::optional<std::vector<unsigned char>> 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<std::vector<unsigned char>> 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<uint8_t> 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<unsigned char> 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<std::vector<unsigned char>> DecodeBase32(const std::string& str) -{ - if (!ValidAsCString(str)) { - return {}; - } - return DecodeBase32(str.c_str()); -} - namespace { template <typename T> 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<std::vector<unsigned char>> DecodeBase64(const char* p); -std::optional<std::vector<unsigned char>> DecodeBase64(const std::string& str); +std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str); std::string EncodeBase64(Span<const unsigned char> input); inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } -std::optional<std::vector<unsigned char>> DecodeBase32(const char* p); -std::optional<std::vector<unsigned char>> DecodeBase32(const std::string& str); +std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str); /** * Base32 encode. |