/* try to parse the end (padding) of the base64 input */
i_assert(src_pos < src_size);
- switch (dec->sub_pos) {
- case 0:
- case 1:
- /* no padding expected */
+ if (HAS_ALL_BITS(dec->flags,
+ BASE64_DECODE_FLAG_NO_PADDING)) {
+ /* no padding allowed */
+ i_assert(!dec->seen_padding);
ret = -1;
- break;
- case 2:
- if (unlikely(src_c[src_pos] != '=')) {
- /* invalid character */
- ret = -1;
- break;
- }
- dec->seen_padding = TRUE;
- dec->sub_pos++;
- src_pos++;
- if (src_pos == src_size) {
- ret = 1;
- break;
- }
- /* skip any whitespace in the padding */
- base64_skip_whitespace(dec, src_c, src_size,
- &src_pos);
- if (src_pos == src_size) {
- ret = 1;
- break;
- }
- /* fall through */
- case 3:
- if (unlikely(src_c[src_pos] != '=')) {
- /* invalid character */
+ } else {
+ switch (dec->sub_pos) {
+ case 0:
+ case 1:
+ /* no padding expected */
ret = -1;
break;
- }
- dec->seen_padding = TRUE;
- dec->seen_end = TRUE;
- dec->sub_pos = 0;
- src_pos++;
- /* skip any trailing whitespace */
- base64_skip_whitespace(dec, src_c, src_size,
- &src_pos);
- if (src_pos < src_size) {
- ret = -1;
+ case 2:
+ if (unlikely(src_c[src_pos] != '=')) {
+ /* invalid character */
+ ret = -1;
+ break;
+ }
+ dec->seen_padding = TRUE;
+ dec->sub_pos++;
+ src_pos++;
+ if (src_pos == src_size) {
+ ret = 1;
+ break;
+ }
+ /* skip any whitespace in the padding */
+ base64_skip_whitespace(dec, src_c, src_size,
+ &src_pos);
+ if (src_pos == src_size) {
+ ret = 1;
+ break;
+ }
+ /* fall through */
+ case 3:
+ if (unlikely(src_c[src_pos] != '=')) {
+ /* invalid character */
+ ret = -1;
+ break;
+ }
+ dec->seen_padding = TRUE;
+ dec->seen_end = TRUE;
+ dec->sub_pos = 0;
+ src_pos++;
+ /* skip any trailing whitespace */
+ base64_skip_whitespace(dec, src_c, src_size,
+ &src_pos);
+ if (src_pos < src_size) {
+ ret = -1;
+ break;
+ }
+ if (no_whitespace) {
+ dec->seen_boundary = TRUE;
+ ret = 0;
+ } else {
+ /* more whitespace may follow */
+ ret = 1;
+ }
break;
}
- if (no_whitespace) {
- dec->seen_boundary = TRUE;
- ret = 0;
- } else {
- /* more whitespace may follow */
- ret = 1;
- }
- break;
}
}
i_assert(!dec->finished);
dec->finished = TRUE;
- return (!dec->failed && dec->sub_pos == 0 ? 0 : -1);
+ if (dec->failed)
+ return -1;
+
+ if (HAS_ALL_BITS(dec->flags,
+ BASE64_DECODE_FLAG_NO_PADDING))
+ return 0;
+ return (dec->sub_pos == 0 ? 0 : -1);
}
/*
.src_pos = 0,
.flags = BASE64_DECODE_FLAG_NO_WHITESPACE,
},
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = "\taGVsbG8gd29ybGQ=",
+ .output = "hello world",
+ .ret = -1,
+ .src_pos = 16,
+ },
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = "\taGVsbG8gd29ybGQ",
+ .output = "hello world",
+ .ret = 0,
+ .src_pos = 16,
+ },
{
.scheme = &base64_scheme,
.input = "\nZm9v\n \tIGJh \t\ncml0cw==",
.ret = 0,
.src_pos = UINT_MAX,
},
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = "\nZm9v\n \tIGJh \t\ncml0cw==",
+ .output = "foo barits",
+ .ret = -1,
+ .src_pos = 22,
+ },
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = "\nZm9v\n \tIGJh \t\ncml0cw",
+ .output = "foo barits",
+ .ret = 0,
+ .src_pos = 22,
+ },
{
.scheme = &base64_scheme,
.input = " anVzdCBuaWlu \n",
.ret = 0,
.src_pos = UINT_MAX,
},
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = " anVzdCBuaWlu \n",
+ .output = "just niin",
+ .ret = 0,
+ .src_pos = UINT_MAX,
+ },
{
.scheme = &base64_scheme,
.input = "aGVsb",
.ret = -1,
.src_pos = 5,
},
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input = "aGVsb",
+ .output = "hel",
+ .ret = 0,
+ .src_pos = 5,
+ },
{
.scheme = &base64_scheme,
.input = "aGVsb!!!!!",
.ret = 0,
.src_pos = UINT_MAX,
},
+ {
+ .scheme = &base64_scheme,
+ .flags = BASE64_DECODE_FLAG_NO_PADDING,
+ .input =
+ "0JPQvtCy0L7RgNGPzIHRgiwg0YfRgt"
+ "C+INC60YPRgCDQtNC+0Y/MgdGCLg",
+ .output =
+ "\xd0\x93\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x80\xd1\x8f\xcc"
+ "\x81\xd1\x82\x2c\x20\xd1\x87\xd1\x82\xd0\xbe\x20\xd0"
+ "\xba\xd1\x83\xd1\x80\x20\xd0\xb4\xd0\xbe\xd1\x8f\xcc"
+ "\x81\xd1\x82\x2e",
+ .ret = 0,
+ .src_pos = UINT_MAX,
+ },
};
static void test_base64_decode_lowlevel(void)
BASE64_ENCODE_FLAG_CRLF, 0, 10);
test_base64_random_lowlevel_case(&base64url_scheme,
BASE64_ENCODE_FLAG_CRLF, 0, 10);
+ test_base64_random_lowlevel_case(&base64_scheme,
+ BASE64_ENCODE_FLAG_NO_PADDING,
+ BASE64_DECODE_FLAG_NO_PADDING, 0);
+ test_base64_random_lowlevel_case(&base64url_scheme,
+ BASE64_ENCODE_FLAG_NO_PADDING,
+ BASE64_DECODE_FLAG_NO_PADDING, 0);
+ test_base64_random_lowlevel_case(&base64_scheme,
+ BASE64_ENCODE_FLAG_NO_PADDING |
+ BASE64_ENCODE_FLAG_CRLF,
+ BASE64_DECODE_FLAG_NO_PADDING, 15);
+ test_base64_random_lowlevel_case(&base64url_scheme,
+ BASE64_ENCODE_FLAG_NO_PADDING |
+ BASE64_ENCODE_FLAG_CRLF,
+ BASE64_DECODE_FLAG_NO_PADDING, 15);
test_end();
}