@@ -126,7 +126,7 @@ std::string EncodeBase64(Span<const unsigned char> input)
126
126
return str;
127
127
}
128
128
129
- std::optional<std::vector<unsigned char >> DecodeBase64 (const char * p )
129
+ std::optional<std::vector<unsigned char >> DecodeBase64 (std::string_view str )
130
130
{
131
131
static const int8_t decode64_table[256 ]{
132
132
-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)
144
144
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
145
145
};
146
146
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 );
156
151
157
152
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
+ );
170
159
if (!valid) return {};
171
160
172
161
return ret;
173
162
}
174
163
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
-
183
164
std::string EncodeBase32 (Span<const unsigned char > input, bool pad)
184
165
{
185
166
static const char *pbase32 = " abcdefghijklmnopqrstuvwxyz234567" ;
@@ -200,7 +181,7 @@ std::string EncodeBase32(const std::string& str, bool pad)
200
181
return EncodeBase32 (MakeUCharSpan (str), pad);
201
182
}
202
183
203
- std::optional<std::vector<unsigned char >> DecodeBase32 (const char * p )
184
+ std::optional<std::vector<unsigned char >> DecodeBase32 (std::string_view str )
204
185
{
205
186
static const int8_t decode32_table[256 ]{
206
187
-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)
218
199
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
219
200
};
220
201
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 );
230
208
231
209
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
+
244
217
if (!valid) return {};
245
218
246
219
return ret;
247
220
}
248
221
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
-
257
222
namespace {
258
223
template <typename T>
259
224
bool ParseIntegral (const std::string& str, T* out)
0 commit comments