Prevent out of bound read in do_buf (a_strex).
(Imported from upstream's 7e6c0f56e65af0727d87615342df1272cd017e9f)
Change-Id: I1d060055c923f78311265510a3fbe17a34ecc1d4
Reviewed-on: https://boringssl-review.googlesource.com/28084
Commit-Queue: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/x509/a_strex.c b/crypto/x509/a_strex.c
index 465ad08..c0c346d 100644
--- a/crypto/x509/a_strex.c
+++ b/crypto/x509/a_strex.c
@@ -178,18 +178,37 @@
int type, unsigned char flags, char *quotes, char_io *io_ch,
void *arg)
{
- int i, outlen, len;
+ int i, outlen, len, charwidth;
unsigned char orflags, *p, *q;
uint32_t c;
p = buf;
q = buf + buflen;
outlen = 0;
+ charwidth = type & BUF_TYPE_WIDTH_MASK;
+
+ switch (charwidth) {
+ case 4:
+ if (buflen & 3) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+ return -1;
+ }
+ break;
+ case 2:
+ if (buflen & 1) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+
while (p != q) {
if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_FIRST_ESC_2253;
else
orflags = 0;
- switch (type & BUF_TYPE_WIDTH_MASK) {
+ switch (charwidth) {
case 4:
c = ((uint32_t)*p++) << 24;
c |= ((uint32_t)*p++) << 16;
@@ -210,6 +229,7 @@
i = UTF8_getc(p, buflen, &c);
if (i < 0)
return -1; /* Invalid UTF8String */
+ buflen -= i;
p += i;
break;
default: