aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2022-04-04 14:10:10 -0400
committerMacroFake <falke.marco@gmail.com>2022-04-27 14:12:55 +0200
commit8ffbd1412d887535ce5eb613884858c319bd12be (patch)
treeb5389e1e788d87fc12edcd7dfe94fbad3b87647e
parent1a72d62152bfdd7c5c2b2704b679f894e7d35e37 (diff)
Make DecodeBase{32,64} take string_view arguments
-rw-r--r--src/netaddress.cpp2
-rw-r--r--src/util/strencodings.cpp85
-rw-r--r--src/util/strencodings.h6
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.