@@ -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-
183164std::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-
257222namespace {
258223template <typename T>
259224bool ParseIntegral (const std::string& str, T* out)
0 commit comments