diff options
author | emaste <emaste@FreeBSD.org> | 2015-03-23 20:50:28 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2015-03-23 20:50:28 +0000 |
commit | 2c2450125c1aac8fb110c1cf19a9dd7bfe1434b5 (patch) | |
tree | dd5b9f7f5a1e02f917f4a53372fdbb04744e857e /lib/libc/net | |
parent | d201e39fd34bb07644b00c9902c809c1d06618d3 (diff) | |
download | FreeBSD-src-2c2450125c1aac8fb110c1cf19a9dd7bfe1434b5.zip FreeBSD-src-2c2450125c1aac8fb110c1cf19a9dd7bfe1434b5.tar.gz |
MFC r275060: Fix b64_pton output buffer overrun test for exact-sized buffer
b64_pton would sometimes erroneously fail to decode a base64 string into
a precisely sized buffer. The overflow check was a little too greedy.
Diffstat (limited to 'lib/libc/net')
-rw-r--r-- | lib/libc/net/base64.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c index 4335030..6737c18 100644 --- a/lib/libc/net/base64.c +++ b/lib/libc/net/base64.c @@ -199,6 +199,7 @@ b64_pton(src, target, targsize) size_t targsize; { int tarindex, state, ch; + u_char nextbyte; char *pos; state = 0; @@ -226,22 +227,28 @@ b64_pton(src, target, targsize) break; case 1: if (target) { - if ((size_t)tarindex + 1 >= targsize) + if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; + nextbyte = ((pos - Base64) & 0x0f) << 4; + if ((size_t)tarindex + 1 < targsize) + target[tarindex + 1] = nextbyte; + else if (nextbyte) + return (-1); } tarindex++; state = 2; break; case 2: if (target) { - if ((size_t)tarindex + 1 >= targsize) + if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; + nextbyte = ((pos - Base64) & 0x03) << 6; + if ((size_t)tarindex + 1 < targsize) + target[tarindex + 1] = nextbyte; + else if (nextbyte) + return (-1); } tarindex++; state = 3; @@ -299,7 +306,8 @@ b64_pton(src, target, targsize) * zeros. If we don't check them, they become a * subliminal channel. */ - if (target && target[tarindex] != 0) + if (target && (size_t)tarindex < targsize && + target[tarindex] != 0) return (-1); } } else { |