Fix boundary conditions in base64_decode
@@ -127,13 +127,13 @@ static size_t base64_encoded_size(size_t len, int mode)
static size_t base64_decoded_size(size_t len)
{
size_t k = len % 4;
- size_t n = ((len + 3) / 4 * 3);
+ size_t n = len / 4 * 3;
switch (k) {
case 3:
- return n - 1;
+ return n + 2;
case 2:
- return n - 2;
+ return n + 1;
case 1: /* Not valid without padding. */
case 0:
default:
@@ -374,8 +374,7 @@ static int base64_decode(uint8_t *dst, const uint8_t *src, size_t *dst_len, size
}
}
if (limit < 3) {
- ret = BASE64_EMORE;
- goto done;
+ goto more;
}
dst[0] = (hold[0] << 2) | (hold[1] >> 4);
dst[1] = (hold[1] << 4) | (hold[2] >> 2);
@@ -396,10 +395,6 @@ done:
return ret;
tail:
- if (limit < k) {
- ret = BASE64_EMORE;
- goto done;
- }
switch (k) {
case 0:
break;
@@ -407,6 +402,9 @@ tail:
if ((hold[1] << 4) & 0xff) {
goto dirty;
}
+ if (limit < 1) {
+ goto more;
+ }
dst[0] = (hold[0] << 2) | (hold[1] >> 4);
dst += 1;
break;
@@ -414,6 +412,9 @@ tail:
if ((hold[2] << 6) & 0xff) {
goto dirty;
}
+ if (limit < 2) {
+ goto more;
+ }
dst[0] = (hold[0] << 2) | (hold[1] >> 4);
dst[1] = (hold[1] << 4) | (hold[2] >> 2);
dst += 2;
@@ -427,6 +428,9 @@ tail:
dirty:
ret = BASE64_EDIRTY;
goto done;
+more:
+ ret = BASE64_EMORE;
+ goto done;
}
#endif /* PBASE64_H */
