@@ -52,36 +52,33 @@ extern const int8_t unbase64_table[256];
52
52
53
53
54
54
template <typename TypeName>
55
- size_t base64_decode_slow (char * dst, size_t dstlen,
56
- const TypeName* src, size_t srclen) {
55
+ bool base64_decode_group_slow (char * const dst, const size_t dstlen,
56
+ const TypeName* const src, const size_t srclen,
57
+ size_t * const i, size_t * const k) {
57
58
uint8_t hi;
58
59
uint8_t lo;
59
- size_t i = 0 ;
60
- size_t k = 0 ;
61
- for (;;) {
62
60
#define V (expr ) \
63
- for (;;) { \
64
- const uint8_t c = src[i]; \
65
- lo = unbase64 (c); \
66
- i += 1 ; \
67
- if (lo < 64 ) \
68
- break ; /* Legal character. */ \
69
- if (c == ' =' || i >= srclen) \
70
- return k ; \
71
- } \
72
- expr; \
73
- if (i >= srclen) \
74
- return k; \
75
- if (k >= dstlen) \
76
- return k; \
77
- hi = lo;
78
- V (/* Nothing. */ );
79
- V (dst[k ++] = ((hi & 0x3F ) << 2 ) | ((lo & 0x30 ) >> 4 ));
80
- V (dst[k ++] = ((hi & 0x0F ) << 4 ) | ((lo & 0x3C ) >> 2 ));
81
- V (dst[k ++] = ((hi & 0x03 ) << 6 ) | ((lo & 0x3F ) >> 0 ));
61
+ for (;;) { \
62
+ const uint8_t c = src[* i]; \
63
+ lo = unbase64 (c); \
64
+ * i += 1 ; \
65
+ if (lo < 64 ) \
66
+ break ; /* Legal character. */ \
67
+ if (c == ' =' || * i >= srclen) \
68
+ return false ; /* Stop decoding. */ \
69
+ } \
70
+ expr; \
71
+ if (* i >= srclen) \
72
+ return false ; \
73
+ if (* k >= dstlen) \
74
+ return false ; \
75
+ hi = lo;
76
+ V (/* Nothing. */ );
77
+ V (dst[(*k) ++] = ((hi & 0x3F ) << 2 ) | ((lo & 0x30 ) >> 4 ));
78
+ V (dst[(*k) ++] = ((hi & 0x0F ) << 4 ) | ((lo & 0x3C ) >> 2 ));
79
+ V (dst[(*k) ++] = ((hi & 0x03 ) << 6 ) | ((lo & 0x3F ) >> 0 ));
82
80
#undef V
83
- }
84
- UNREACHABLE ();
81
+ return true ; // Continue decoding.
85
82
}
86
83
87
84
@@ -90,8 +87,8 @@ size_t base64_decode_fast(char* const dst, const size_t dstlen,
90
87
const TypeName* const src, const size_t srclen,
91
88
const size_t decoded_size) {
92
89
const size_t available = dstlen < decoded_size ? dstlen : decoded_size;
93
- const size_t max_i = srclen / 4 * 4 ;
94
90
const size_t max_k = available / 3 * 3 ;
91
+ size_t max_i = srclen / 4 * 4 ;
95
92
size_t i = 0 ;
96
93
size_t k = 0 ;
97
94
while (i < max_i && k < max_k) {
@@ -102,16 +99,20 @@ size_t base64_decode_fast(char* const dst, const size_t dstlen,
102
99
unbase64 (src[i + 3 ]);
103
100
// If MSB is set, input contains whitespace or is not valid base64.
104
101
if (v & 0x80808080 ) {
105
- break ;
102
+ const size_t old_i = i;
103
+ if (!base64_decode_group_slow (dst, dstlen, src, srclen, &i, &k))
104
+ return k;
105
+ max_i = old_i + (srclen - i) / 4 * 4 ; // Align max_i again.
106
+ } else {
107
+ dst[k + 0 ] = ((v >> 22 ) & 0xFC ) | ((v >> 20 ) & 0x03 );
108
+ dst[k + 1 ] = ((v >> 12 ) & 0xF0 ) | ((v >> 10 ) & 0x0F );
109
+ dst[k + 2 ] = ((v >> 2 ) & 0xC0 ) | ((v >> 0 ) & 0x3F );
110
+ i += 4 ;
111
+ k += 3 ;
106
112
}
107
- dst[k + 0 ] = ((v >> 22 ) & 0xFC ) | ((v >> 20 ) & 0x03 );
108
- dst[k + 1 ] = ((v >> 12 ) & 0xF0 ) | ((v >> 10 ) & 0x0F );
109
- dst[k + 2 ] = ((v >> 2 ) & 0xC0 ) | ((v >> 0 ) & 0x3F );
110
- i += 4 ;
111
- k += 3 ;
112
113
}
113
114
if (i < srclen && k < dstlen) {
114
- return k + base64_decode_slow (dst + k , dstlen - k , src + i , srclen - i );
115
+ base64_decode_group_slow (dst, dstlen, src, srclen, &i, &k );
115
116
}
116
117
return k;
117
118
}
0 commit comments