((c) == '\n' || (c) == '\r' || (c) == ' ' || (c) == '\t')
static inline void
-base64_skip_whitespace(struct base64_decoder *dec ATTR_UNUSED,
- const unsigned char *src_c,
+base64_skip_whitespace(struct base64_decoder *dec, const unsigned char *src_c,
size_t src_size, size_t *src_pos)
{
+ if (HAS_ALL_BITS(dec->flags, BASE64_DECODE_FLAG_NO_WHITESPACE))
+ return;
+
/* skip any whitespace in the padding */
while ((*src_pos) < src_size && IS_EMPTY(src_c[(*src_pos)]))
(*src_pos)++;
const unsigned char *src_c = src;
bool expect_boundary = HAS_ALL_BITS(dec->flags,
BASE64_DECODE_FLAG_EXPECT_BOUNDARY);
+ bool no_whitespace = HAS_ALL_BITS(dec->flags,
+ BASE64_DECODE_FLAG_NO_WHITESPACE);
size_t src_pos, dst_avail;
int ret = 1;
dec->seen_boundary = TRUE;
return 0;
}
+ if (no_whitespace) {
+ dec->seen_boundary = TRUE;
+ return 0;
+ }
/* more whitespace may follow */
return 1;
}
unsigned char dm = b64->decmap[in];
if (dm == 0xff) {
+ if (no_whitespace) {
+ ret = -1;
+ break;
+ }
if (unlikely(!IS_EMPTY(in))) {
ret = -1;
break;
ret = -1;
break;
}
- /* more whitespace may follow */
- ret = 1;
+ if (no_whitespace) {
+ dec->seen_boundary = TRUE;
+ ret = 0;
+ } else {
+ /* more whitespace may follow */
+ ret = 1;
+ }
break;
}
}
to decode such a Base64 prefix. The base64_decode_finish() function
will still check that the Base64 data ends properly (padding). */
BASE64_DECODE_FLAG_EXPECT_BOUNDARY = BIT(0),
+ /* Prohibit whitespace in the input. */
+ BASE64_DECODE_FLAG_NO_WHITESPACE = BIT(1),
};
struct base64_decoder {
buffer. dest may point to same buffer as src. Returns 1 if all ok, 0 if end
of base64 data found, -1 if data is invalid.
- Any CR, LF characters are ignored, as well as whitespace at beginning or end
- of line.
+ By default, any CR, LF characters are ignored, as well as any whitespace.
+ This can be overridden using the BASE64_DECODE_FLAG_NO_WHITESPACE flag.
If src_pos is non-NULL, it's updated to first non-translated character in
src.
.ret = 0,
.src_pos = UINT_MAX,
},
+ {
+ .scheme = &base64_scheme,
+ .input = "aGVsbG8gd29ybGQ=\t",
+ .output = "hello world",
+ .ret = 0,
+ .src_pos = UINT_MAX,
+ },
{
.scheme = &base64_scheme,
.input = "\taGVsbG8gd29ybGQ=\t",
.src_pos = 18,
.flags = BASE64_DECODE_FLAG_EXPECT_BOUNDARY,
},
+ {
+ .scheme = &base64_scheme,
+ .input = "aGVsbG8gd29ybGQ=\t",
+ .output = "hello world",
+ .ret = -1,
+ .src_pos = 16,
+ .flags = BASE64_DECODE_FLAG_NO_WHITESPACE,
+ },
+ {
+ .scheme = &base64_scheme,
+ .input = "\taGVsbG8gd29ybGQ=\t",
+ .output = "",
+ .ret = -1,
+ .src_pos = 0,
+ .flags = BASE64_DECODE_FLAG_NO_WHITESPACE,
+ },
{
.scheme = &base64_scheme,
.input = "\nZm9v\n \tIGJh \t\ncml0cw==",
BASE64_DECODE_FLAG_EXPECT_BOUNDARY);
test_base64_random_lowlevel_case(&base64url_scheme,
BASE64_DECODE_FLAG_EXPECT_BOUNDARY);
+ test_base64_random_lowlevel_case(&base64_scheme,
+ BASE64_DECODE_FLAG_NO_WHITESPACE);
+ test_base64_random_lowlevel_case(&base64url_scheme,
+ BASE64_DECODE_FLAG_NO_WHITESPACE);
test_end();
}
+
void test_base64(void)
{
test_base64_encode();