Skip to content

Commit 8ffbd14

Browse files
sipaMacroFake
authored andcommitted
Make DecodeBase{32,64} take string_view arguments
1 parent 1a72d62 commit 8ffbd14

File tree

3 files changed

+28
-65
lines changed

3 files changed

+28
-65
lines changed

src/netaddress.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ bool CNetAddr::SetTor(const std::string& addr)
234234
return false;
235235
}
236236

237-
auto input = DecodeBase32(addr.substr(0, addr.size() - suffix_len));
237+
auto input = DecodeBase32(std::string_view{addr}.substr(0, addr.size() - suffix_len));
238238

239239
if (!input) {
240240
return false;

src/util/strencodings.cpp

Lines changed: 25 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ std::string EncodeBase64(Span<const unsigned char> input)
126126
return str;
127127
}
128128

129-
std::optional<std::vector<unsigned char>> DecodeBase64(const char* p)
129+
std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str)
130130
{
131131
static const int8_t decode64_table[256]{
132132
-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)
144144
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
145145
};
146146

147-
const char* e = p;
148-
std::vector<uint8_t> val;
149-
val.reserve(strlen(p));
150-
while (*p != 0) {
151-
int x = decode64_table[(unsigned char)*p];
152-
if (x == -1) break;
153-
val.push_back(uint8_t(x));
154-
++p;
155-
}
147+
if (str.size() % 4 != 0) return {};
148+
/* One or two = characters at the end are permitted. */
149+
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
150+
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
156151

157152
std::vector<unsigned char> ret;
158-
ret.reserve((val.size() * 3) / 4);
159-
bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
160-
161-
const char* q = p;
162-
while (valid && *p != 0) {
163-
if (*p != '=') {
164-
valid = false;
165-
break;
166-
}
167-
++p;
168-
}
169-
valid = valid && (p - e) % 4 == 0 && p - q < 4;
153+
ret.reserve((str.size() * 3) / 4);
154+
bool valid = ConvertBits<6, 8, false>(
155+
[&](unsigned char c) { ret.push_back(c); },
156+
str.begin(), str.end(),
157+
[](char c) { return decode64_table[uint8_t(c)]; }
158+
);
170159
if (!valid) return {};
171160

172161
return ret;
173162
}
174163

175-
std::optional<std::vector<unsigned char>> DecodeBase64(const std::string& str)
176-
{
177-
if (!ValidAsCString(str)) {
178-
return {};
179-
}
180-
return DecodeBase64(str.c_str());
181-
}
182-
183164
std::string EncodeBase32(Span<const unsigned char> input, bool pad)
184165
{
185166
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
@@ -200,7 +181,7 @@ std::string EncodeBase32(const std::string& str, bool pad)
200181
return EncodeBase32(MakeUCharSpan(str), pad);
201182
}
202183

203-
std::optional<std::vector<unsigned char>> DecodeBase32(const char* p)
184+
std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)
204185
{
205186
static const int8_t decode32_table[256]{
206187
-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)
218199
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
219200
};
220201

221-
const char* e = p;
222-
std::vector<uint8_t> val;
223-
val.reserve(strlen(p));
224-
while (*p != 0) {
225-
int x = decode32_table[(unsigned char)*p];
226-
if (x == -1) break;
227-
val.push_back(uint8_t(x));
228-
++p;
229-
}
202+
if (str.size() % 8 != 0) return {};
203+
/* 1, 3, 4, or 6 padding '=' suffix characters are permitted. */
204+
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
205+
if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
206+
if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
207+
if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
230208

231209
std::vector<unsigned char> ret;
232-
ret.reserve((val.size() * 5) / 8);
233-
bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
234-
235-
const char* q = p;
236-
while (valid && *p != 0) {
237-
if (*p != '=') {
238-
valid = false;
239-
break;
240-
}
241-
++p;
242-
}
243-
valid = valid && (p - e) % 8 == 0 && p - q < 8;
210+
ret.reserve((str.size() * 5) / 8);
211+
bool valid = ConvertBits<5, 8, false>(
212+
[&](unsigned char c) { ret.push_back(c); },
213+
str.begin(), str.end(),
214+
[](char c) { return decode32_table[uint8_t(c)]; }
215+
);
216+
244217
if (!valid) return {};
245218

246219
return ret;
247220
}
248221

249-
std::optional<std::vector<unsigned char>> DecodeBase32(const std::string& str)
250-
{
251-
if (!ValidAsCString(str)) {
252-
return {};
253-
}
254-
return DecodeBase32(str.c_str());
255-
}
256-
257222
namespace {
258223
template <typename T>
259224
bool ParseIntegral(const std::string& str, T* out)

src/util/strencodings.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,11 @@ bool IsHex(std::string_view str);
6464
* Return true if the string is a hex number, optionally prefixed with "0x"
6565
*/
6666
bool IsHexNumber(std::string_view str);
67-
std::optional<std::vector<unsigned char>> DecodeBase64(const char* p);
68-
std::optional<std::vector<unsigned char>> DecodeBase64(const std::string& str);
67+
std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str);
6968
std::string EncodeBase64(Span<const unsigned char> input);
7069
inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
7170
inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); }
72-
std::optional<std::vector<unsigned char>> DecodeBase32(const char* p);
73-
std::optional<std::vector<unsigned char>> DecodeBase32(const std::string& str);
71+
std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str);
7472

7573
/**
7674
* Base32 encode.

0 commit comments

Comments
 (0)