8028591: NegativeArraySizeException in sun.security.util.DerInputStream.getUnalignedBitString()
Reviewed-by: mullan, weijun
--- a/jdk/src/share/classes/sun/security/util/DerInputStream.java Thu Mar 13 07:52:17 2014 +0400
+++ b/jdk/src/share/classes/sun/security/util/DerInputStream.java Thu Mar 13 15:13:22 2014 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -167,7 +167,7 @@
if (buffer.read() != DerValue.tag_Integer) {
throw new IOException("DER input, Integer tag error");
}
- return buffer.getInteger(getLength(buffer));
+ return buffer.getInteger(getDefiniteLength(buffer));
}
/**
@@ -179,7 +179,7 @@
if (buffer.read() != DerValue.tag_Integer) {
throw new IOException("DER input, Integer tag error");
}
- return buffer.getBigInteger(getLength(buffer), false);
+ return buffer.getBigInteger(getDefiniteLength(buffer), false);
}
/**
@@ -193,7 +193,7 @@
if (buffer.read() != DerValue.tag_Integer) {
throw new IOException("DER input, Integer tag error");
}
- return buffer.getBigInteger(getLength(buffer), true);
+ return buffer.getBigInteger(getDefiniteLength(buffer), true);
}
/**
@@ -205,7 +205,7 @@
if (buffer.read() != DerValue.tag_Enumerated) {
throw new IOException("DER input, Enumerated tag error");
}
- return buffer.getInteger(getLength(buffer));
+ return buffer.getInteger(getDefiniteLength(buffer));
}
/**
@@ -216,7 +216,7 @@
if (buffer.read() != DerValue.tag_BitString)
throw new IOException("DER input not an bit string");
- return buffer.getBitString(getLength(buffer));
+ return buffer.getBitString(getDefiniteLength(buffer));
}
/**
@@ -224,21 +224,32 @@
* not be byte-aligned.
*/
public BitArray getUnalignedBitString() throws IOException {
- if (buffer.read() != DerValue.tag_BitString)
+ if (buffer.read() != DerValue.tag_BitString) {
throw new IOException("DER input not a bit string");
+ }
- int length = getLength(buffer) - 1;
+ int length = getDefiniteLength(buffer);
+
+ if (length == 0) {
+ return new BitArray(0);
+ }
/*
* First byte = number of excess bits in the last octet of the
* representation.
*/
+ length--;
int validBits = length*8 - buffer.read();
+ if (validBits < 0) {
+ throw new IOException("valid bits of bit string invalid");
+ }
byte[] repn = new byte[length];
- if ((length != 0) && (buffer.read(repn) != length))
+ if ((length != 0) && (buffer.read(repn) != length)) {
throw new IOException("short read of DER bit string");
+ }
+
return new BitArray(validBits, repn);
}
@@ -249,7 +260,7 @@
if (buffer.read() != DerValue.tag_OctetString)
throw new IOException("DER input not an octet string");
- int length = getLength(buffer);
+ int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
throw new IOException("short read of DER octet string");
@@ -363,7 +374,7 @@
if (tag != buffer.read())
throw new IOException("Indefinite length encoding" +
" not supported");
- len = DerInputStream.getLength(buffer);
+ len = DerInputStream.getDefiniteLength(buffer);
}
if (len == 0)
@@ -480,7 +491,7 @@
throw new IOException("DER input not a " +
stringName + " string");
- int length = getLength(buffer);
+ int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
throw new IOException("short read of DER " +
@@ -495,7 +506,7 @@
public Date getUTCTime() throws IOException {
if (buffer.read() != DerValue.tag_UtcTime)
throw new IOException("DER input, UTCtime tag invalid ");
- return buffer.getUTCTime(getLength(buffer));
+ return buffer.getUTCTime(getDefiniteLength(buffer));
}
/**
@@ -504,7 +515,7 @@
public Date getGeneralizedTime() throws IOException {
if (buffer.read() != DerValue.tag_GeneralizedTime)
throw new IOException("DER input, GeneralizedTime tag invalid ");
- return buffer.getGeneralizedTime(getLength(buffer));
+ return buffer.getGeneralizedTime(getDefiniteLength(buffer));
}
/*
@@ -570,6 +581,24 @@
return value;
}
+ int getDefiniteLength() throws IOException {
+ return getDefiniteLength(buffer);
+ }
+
+ /*
+ * Get a length from the input stream.
+ *
+ * @return the length
+ * @exception IOException on parsing error or if indefinite length found.
+ */
+ static int getDefiniteLength(InputStream in) throws IOException {
+ int len = getLength(in);
+ if (len < 0) {
+ throw new IOException("Indefinite length encoding not supported");
+ }
+ return len;
+ }
+
/**
* Mark the current position in the buffer, so that
* a later call to <code>reset</code> will return here.
--- a/jdk/src/share/classes/sun/security/util/DerValue.java Thu Mar 13 07:52:17 2014 +0400
+++ b/jdk/src/share/classes/sun/security/util/DerValue.java Thu Mar 13 15:13:22 2014 +0800
@@ -265,7 +265,7 @@
if (tag != inbuf.read())
throw new IOException
("Indefinite length encoding not supported");
- length = DerInputStream.getLength(inbuf);
+ length = DerInputStream.getDefiniteLength(inbuf);
buffer = inbuf.dup();
buffer.truncate(length);
data = new DerInputStream(buffer);
@@ -377,7 +377,7 @@
if (tag != in.read())
throw new IOException
("Indefinite length encoding not supported");
- length = DerInputStream.getLength(in);
+ length = DerInputStream.getDefiniteLength(in);
}
if (fullyBuffered && in.available() != length)
--- a/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java Thu Mar 13 07:52:17 2014 +0400
+++ b/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java Thu Mar 13 15:13:22 2014 +0800
@@ -255,7 +255,7 @@
+ " (tag = " + type_id + ")"
);
- encoding = new byte[in.getLength()];
+ encoding = new byte[in.getDefiniteLength()];
in.getBytes(encoding);
check(encoding);
}
--- a/jdk/test/java/security/cert/X509Certificate/X509BadCertificate.java Thu Mar 13 07:52:17 2014 +0400
+++ b/jdk/test/java/security/cert/X509Certificate/X509BadCertificate.java Thu Mar 13 15:13:22 2014 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8028431
+ * @bug 8028431 8028591
* @summary Make sure that proper CertificateException is thrown
* when loading bad x509 certificate
* @author Artem Smotrakov
@@ -39,6 +39,7 @@
public static void main(String[] args) throws Exception {
test("bad-cert-1.pem");
+ test("bad-cert-2.pem");
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/cert/X509Certificate/bad-cert-2.pem Thu Mar 13 15:13:22 2014 +0800
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIJAJYB3qu9C2kiMA0GCSqGSIb3DQEBBQUAMEoxDTALBgNV
+BAMMBFRlc3QxDTALBgNVBAsMBEphdmExDzANBgNVBAoMBk9yYWNsZTEMMAoGA1UE
+BwwDU1BCMQswCQYDVQQGEwJSVTAeFw0xMzEyMjMwNzA4MDhaFw0yMzEyMjEwNzA4
+MDhaMEoxDTALBgNVBAMMBFRlc3QxDTALBgNVBAsMBEphdmExDzANBgNVBAoMBk9y
+YWNsZTEMMAoGA1UEBwwDU1BCMQswCQYDVQQGEwJSVTCCASIwDQYJKoZIhvcNAQEB
+BQADgGEPADCCAQoCggEBAOqiCN4gFxehl547Q7/VNGbGApr+wszLdanHPucAH6Wf
+LtcRhKNUSqtBAQxEpFrTpMNEqm2GElAjiPa6m48qIjLVSvOb/9w3G/yXB8zyZbIm
+/Nfp2sT4OEaa1JSEZSpolhS4FfqYzjGQp5cn4Xn4zKjDgiceHgfLls5x2dRydQZO
+Yf91qSIioZxVHUtlo8yztkieiSaqPWt3nJ4PIwhFbsu1HVmWaYZD+nBYCKgVHqrS
+cueO98Ca4Doz73O27X1dVbQBdLS0JI7qVAG8LD388iPL8qbsOkgWPzmEQ+kLRKO4
+g7RpuwlXuwaMSh95NWaxlu4Ob6GRJQmpconYoe13+7ECAwEAAaNQME4wHQYDVR0O
+BBYEFIG8TPobXcbNbDi+zKudd9whpxoNMB8GA1UdIwQYMBaAFIG8TPobXcbNbDi+
+zKudd9whpxoNMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAynN+e7
+h+ufT5SBKN/gBuJAnF1mKIPESiipuv5KoYUGZOY8ShgYLcwY+qnbuHYFUlvq6Zns
+K4/e+x/16h32vD7dEPkNvukbvER4YJQQiN6osDfXpTPzixYftWdmtX0u8xQfwb/g
+R8DS7bazz99jVXk+jTK4yWBY+gMwEat+LyNQ5cyq8Qhi1oBKUbGRbiOts19B97fn
+Rv8TsyXN3INLGYhdVxZoD7E5tyG1ydSFmOMadulAC2epBXDHOXZnz2UWauJc0XW5
+1L/YQVri47VkdHS3tisBzELEJdLmdMDb+5tAU+lItXmTXe2/PB53WIvsEIb4t+eQ
+wY0hCj9lVJlajTQ=
+-----END CERTIFICATE-----