mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 10:34:38 +02:00
Merge
This commit is contained in:
commit
1982432db4
992 changed files with 2142 additions and 2081 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
|
@ -939,8 +939,6 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
*/
|
||||
private static class DeserializationChecker implements ObjectInputFilter {
|
||||
|
||||
private static final int MAX_NESTED_DEPTH = 2;
|
||||
|
||||
// Full length of keystore, anything inside a SecretKeyEntry should not
|
||||
// be bigger. Otherwise, must be illegal.
|
||||
private final int fullLength;
|
||||
|
@ -953,16 +951,29 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
public ObjectInputFilter.Status
|
||||
checkInput(ObjectInputFilter.FilterInfo info) {
|
||||
|
||||
// First run a custom filter
|
||||
long nestedDepth = info.depth();
|
||||
if ((nestedDepth == 1 &&
|
||||
info.serialClass() != SealedObjectForKeyProtector.class) ||
|
||||
info.arrayLength() > fullLength ||
|
||||
(nestedDepth > MAX_NESTED_DEPTH &&
|
||||
info.serialClass() != null &&
|
||||
info.serialClass() != Object.class)) {
|
||||
if (info.arrayLength() > fullLength) {
|
||||
return Status.REJECTED;
|
||||
}
|
||||
// First run a custom filter
|
||||
Class<?> clazz = info.serialClass();
|
||||
switch((int)info.depth()) {
|
||||
case 1:
|
||||
if (clazz != SealedObjectForKeyProtector.class) {
|
||||
return Status.REJECTED;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (clazz != null && clazz != SealedObject.class
|
||||
&& clazz != byte[].class) {
|
||||
return Status.REJECTED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (clazz != null && clazz != Object.class) {
|
||||
return Status.REJECTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Next run the default filter, if available
|
||||
ObjectInputFilter defaultFilter =
|
||||
|
|
|
@ -49,6 +49,7 @@ import static java.io.ObjectStreamClass.processQueue;
|
|||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
|
||||
/**
|
||||
* An ObjectInputStream deserializes primitive data and objects previously
|
||||
|
@ -294,6 +295,14 @@ public class ObjectInputStream
|
|||
/** queue for WeakReferences to audited subclasses */
|
||||
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
|
||||
new ReferenceQueue<>();
|
||||
|
||||
/**
|
||||
* Property to permit setting a filter after objects
|
||||
* have been read.
|
||||
* See {@link #setObjectInputFilter(ObjectInputFilter)}
|
||||
*/
|
||||
static final boolean SET_FILTER_AFTER_READ = GetBooleanAction
|
||||
.privilegedGetProperty("jdk.serialSetFilterAfterRead");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1260,6 +1269,8 @@ public class ObjectInputStream
|
|||
* {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}
|
||||
* when the {@code ObjectInputStream} is constructed and can be set
|
||||
* to a custom filter only once.
|
||||
* The filter must be set before reading any objects from the stream;
|
||||
* for example, by calling {@link #readObject} or {@link #readUnshared}.
|
||||
*
|
||||
* @implSpec
|
||||
* The filter, when not {@code null}, is invoked during {@link #readObject readObject}
|
||||
|
@ -1302,7 +1313,8 @@ public class ObjectInputStream
|
|||
* @throws SecurityException if there is security manager and the
|
||||
* {@code SerializablePermission("serialFilter")} is not granted
|
||||
* @throws IllegalStateException if the {@linkplain #getObjectInputFilter() current filter}
|
||||
* is not {@code null} and is not the system-wide filter
|
||||
* is not {@code null} and is not the system-wide filter, or
|
||||
* if an object has been read
|
||||
* @since 9
|
||||
*/
|
||||
public final void setObjectInputFilter(ObjectInputFilter filter) {
|
||||
|
@ -1315,6 +1327,10 @@ public class ObjectInputStream
|
|||
serialFilter != ObjectInputFilter.Config.getSerialFilter()) {
|
||||
throw new IllegalStateException("filter can not be set more than once");
|
||||
}
|
||||
if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {
|
||||
throw new IllegalStateException(
|
||||
"filter can not be set after an object has been read");
|
||||
}
|
||||
this.serialFilter = filter;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, 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
|
||||
|
@ -364,8 +364,8 @@ public abstract class Buffer {
|
|||
if (newLimit > capacity | newLimit < 0)
|
||||
throw createLimitException(newLimit);
|
||||
limit = newLimit;
|
||||
if (position > limit) position = limit;
|
||||
if (mark > limit) mark = -1;
|
||||
if (position > newLimit) position = newLimit;
|
||||
if (mark > newLimit) mark = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -689,16 +689,18 @@ public abstract class Buffer {
|
|||
* @return The current position value, before it is incremented
|
||||
*/
|
||||
final int nextGetIndex() { // package-private
|
||||
if (position >= limit)
|
||||
int p = position;
|
||||
if (p >= limit)
|
||||
throw new BufferUnderflowException();
|
||||
return position++;
|
||||
position = p + 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
final int nextGetIndex(int nb) { // package-private
|
||||
if (limit - position < nb)
|
||||
throw new BufferUnderflowException();
|
||||
int p = position;
|
||||
position += nb;
|
||||
if (limit - p < nb)
|
||||
throw new BufferUnderflowException();
|
||||
position = p + nb;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -710,16 +712,18 @@ public abstract class Buffer {
|
|||
* @return The current position value, before it is incremented
|
||||
*/
|
||||
final int nextPutIndex() { // package-private
|
||||
if (position >= limit)
|
||||
int p = position;
|
||||
if (p >= limit)
|
||||
throw new BufferOverflowException();
|
||||
return position++;
|
||||
position = p + 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
final int nextPutIndex(int nb) { // package-private
|
||||
if (limit - position < nb)
|
||||
throw new BufferOverflowException();
|
||||
int p = position;
|
||||
position += nb;
|
||||
if (limit - p < nb)
|
||||
throw new BufferOverflowException();
|
||||
position = p + nb;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2020, 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
|
||||
|
@ -3702,6 +3702,8 @@ public final class Files {
|
|||
Objects.requireNonNull(cs);
|
||||
|
||||
byte[] bytes = JLA.getBytesNoRepl(String.valueOf(csq), cs);
|
||||
if (path.getClass().getModule() != Object.class.getModule())
|
||||
bytes = bytes.clone();
|
||||
write(path, bytes, options);
|
||||
|
||||
return path;
|
||||
|
|
|
@ -465,8 +465,10 @@ public abstract class MessageDigest extends MessageDigestSpi {
|
|||
* the same length and all bytes at corresponding positions are equal.
|
||||
*
|
||||
* @implNote
|
||||
* If the digests are the same length, all bytes are examined to
|
||||
* determine equality.
|
||||
* All bytes in {@code digesta} are examined to determine equality.
|
||||
* The calculation time depends only on the length of {@code digesta}.
|
||||
* It does not depend on the length of {@code digestb} or the contents
|
||||
* of {@code digesta} and {@code digestb}.
|
||||
*
|
||||
* @param digesta one of the digests to compare.
|
||||
*
|
||||
|
@ -479,14 +481,22 @@ public abstract class MessageDigest extends MessageDigestSpi {
|
|||
if (digesta == null || digestb == null) {
|
||||
return false;
|
||||
}
|
||||
if (digesta.length != digestb.length) {
|
||||
return false;
|
||||
|
||||
int lenA = digesta.length;
|
||||
int lenB = digestb.length;
|
||||
|
||||
if (lenB == 0) {
|
||||
return lenA == 0;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
result |= lenA - lenB;
|
||||
|
||||
// time-constant comparison
|
||||
for (int i = 0; i < digesta.length; i++) {
|
||||
result |= digesta[i] ^ digestb[i];
|
||||
for (int i = 0; i < lenA; i++) {
|
||||
// If i >= lenB, indexB is 0; otherwise, i.
|
||||
int indexB = ((i - lenB) >>> 31) * i;
|
||||
result |= digesta[i] ^ digestb[indexB];
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
|
|
@ -254,6 +254,9 @@ public final class PKCS12Attribute implements KeyStore.Entry.Attribute {
|
|||
private void parse(byte[] encoded) throws IOException {
|
||||
DerInputStream attributeValue = new DerInputStream(encoded);
|
||||
DerValue[] attrSeq = attributeValue.getSequence(2);
|
||||
if (attrSeq.length != 2) {
|
||||
throw new IOException("Invalid length for PKCS12Attribute");
|
||||
}
|
||||
ObjectIdentifier type = attrSeq[0].getOID();
|
||||
DerInputStream attrContent =
|
||||
new DerInputStream(attrSeq[1].toByteArray());
|
||||
|
|
|
@ -178,15 +178,16 @@ public class ArrayList<E> extends AbstractList<E>
|
|||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public ArrayList(Collection<? extends E> c) {
|
||||
elementData = c.toArray();
|
||||
if ((size = elementData.length) != 0) {
|
||||
// defend against c.toArray (incorrectly) not returning Object[]
|
||||
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
|
||||
if (elementData.getClass() != Object[].class)
|
||||
elementData = Arrays.copyOf(elementData, size, Object[].class);
|
||||
Object[] a = c.toArray();
|
||||
if ((size = a.length) != 0) {
|
||||
if (c.getClass() == ArrayList.class) {
|
||||
elementData = a;
|
||||
} else {
|
||||
elementData = Arrays.copyOf(a, size, Object[].class);
|
||||
}
|
||||
} else {
|
||||
// replace with empty array.
|
||||
this.elementData = EMPTY_ELEMENTDATA;
|
||||
elementData = EMPTY_ELEMENTDATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -263,8 +263,7 @@ public class PriorityQueue<E> extends AbstractQueue<E>
|
|||
private void initElementsFromCollection(Collection<? extends E> c) {
|
||||
Object[] es = c.toArray();
|
||||
int len = es.length;
|
||||
// If c.toArray incorrectly doesn't return Object[], copy it.
|
||||
if (es.getClass() != Object[].class)
|
||||
if (c.getClass() != ArrayList.class)
|
||||
es = Arrays.copyOf(es, len, Object[].class);
|
||||
if (len == 1 || this.comparator != null)
|
||||
for (Object e : es)
|
||||
|
|
|
@ -179,12 +179,13 @@ public class Vector<E>
|
|||
* @since 1.2
|
||||
*/
|
||||
public Vector(Collection<? extends E> c) {
|
||||
elementData = c.toArray();
|
||||
elementCount = elementData.length;
|
||||
// defend against c.toArray (incorrectly) not returning Object[]
|
||||
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
|
||||
if (elementData.getClass() != Object[].class)
|
||||
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
|
||||
Object[] a = c.toArray();
|
||||
elementCount = a.length;
|
||||
if (c.getClass() == ArrayList.class) {
|
||||
elementData = a;
|
||||
} else {
|
||||
elementData = Arrays.copyOf(a, elementCount, Object[].class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,6 +36,7 @@ package java.util.concurrent;
|
|||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
@ -139,9 +140,7 @@ public class CopyOnWriteArrayList<E>
|
|||
es = ((CopyOnWriteArrayList<?>)c).getArray();
|
||||
else {
|
||||
es = c.toArray();
|
||||
// defend against c.toArray (incorrectly) not returning Object[]
|
||||
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
|
||||
if (es.getClass() != Object[].class)
|
||||
if (c.getClass() != java.util.ArrayList.class)
|
||||
es = Arrays.copyOf(es, es.length, Object[].class);
|
||||
}
|
||||
setArray(es);
|
||||
|
@ -690,6 +689,9 @@ public class CopyOnWriteArrayList<E>
|
|||
*/
|
||||
public int addAllAbsent(Collection<? extends E> c) {
|
||||
Object[] cs = c.toArray();
|
||||
if (c.getClass() != ArrayList.class) {
|
||||
cs = cs.clone();
|
||||
}
|
||||
if (cs.length == 0)
|
||||
return 0;
|
||||
synchronized (lock) {
|
||||
|
@ -741,9 +743,10 @@ public class CopyOnWriteArrayList<E>
|
|||
Object[] es = getArray();
|
||||
int len = es.length;
|
||||
Object[] newElements;
|
||||
if (len == 0 && cs.getClass() == Object[].class)
|
||||
if (len == 0 && (c.getClass() == CopyOnWriteArrayList.class ||
|
||||
c.getClass() == ArrayList.class)) {
|
||||
newElements = cs;
|
||||
else {
|
||||
} else {
|
||||
newElements = Arrays.copyOf(es, len + cs.length);
|
||||
System.arraycopy(cs, 0, newElements, len, cs.length);
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class ForkJoinWorkerThread extends Thread {
|
|||
final ForkJoinPool pool; // the pool this thread works in
|
||||
final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
|
||||
|
||||
/** An AccessControlContext supporting no privileges */
|
||||
private static final AccessControlContext INNOCUOUS_ACC =
|
||||
new AccessControlContext(
|
||||
new ProtectionDomain[] { new ProtectionDomain(null, null) });
|
||||
|
||||
/**
|
||||
* Creates a ForkJoinWorkerThread operating in the given pool.
|
||||
*
|
||||
|
@ -99,6 +104,7 @@ public class ForkJoinWorkerThread extends Thread {
|
|||
ForkJoinWorkerThread(ForkJoinPool pool, ClassLoader ccl) {
|
||||
super("aForkJoinWorkerThread");
|
||||
super.setContextClassLoader(ccl);
|
||||
ThreadLocalRandom.setInheritedAccessControlContext(this, INNOCUOUS_ACC);
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
}
|
||||
|
@ -214,11 +220,6 @@ public class ForkJoinWorkerThread extends Thread {
|
|||
group, "InnocuousForkJoinWorkerThreadGroup");
|
||||
}});
|
||||
|
||||
/** An AccessControlContext supporting no privileges */
|
||||
private static final AccessControlContext INNOCUOUS_ACC =
|
||||
new AccessControlContext(
|
||||
new ProtectionDomain[] { new ProtectionDomain(null, null) });
|
||||
|
||||
InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
|
||||
super(pool,
|
||||
ClassLoader.getSystemClassLoader(),
|
||||
|
|
|
@ -257,8 +257,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
|
|||
}
|
||||
Object[] es = c.toArray();
|
||||
int n = es.length;
|
||||
// If c.toArray incorrectly doesn't return Object[], copy it.
|
||||
if (es.getClass() != Object[].class)
|
||||
if (c.getClass() != java.util.ArrayList.class)
|
||||
es = Arrays.copyOf(es, n, Object[].class);
|
||||
if (screen && (n == 1 || this.comparator != null)) {
|
||||
for (Object e : es)
|
||||
|
|
|
@ -86,10 +86,14 @@ class ZipCoder {
|
|||
}
|
||||
}
|
||||
|
||||
String toStringUTF8(byte[] ba, int len) {
|
||||
static String toStringUTF8(byte[] ba, int len) {
|
||||
return UTF8.toString(ba, 0, len);
|
||||
}
|
||||
|
||||
static String toStringUTF8(byte[] ba, int off, int len) {
|
||||
return UTF8.toString(ba, off, len);
|
||||
}
|
||||
|
||||
boolean isUTF8() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -795,7 +795,6 @@ public class ZipFile implements ZipConstants, Closeable {
|
|||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1311,6 +1310,44 @@ public class ZipFile implements ZipConstants, Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
private static final void checkUTF8(byte[] a, int pos, int len) throws ZipException {
|
||||
try {
|
||||
int end = pos + len;
|
||||
while (pos < end) {
|
||||
// ASCII fast-path: When checking that a range of bytes is
|
||||
// valid UTF-8, we can avoid some allocation by skipping
|
||||
// past bytes in the 0-127 range
|
||||
if (a[pos] < 0) {
|
||||
ZipCoder.toStringUTF8(a, pos, end - pos);
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
zerror("invalid CEN header (bad entry name)");
|
||||
}
|
||||
}
|
||||
|
||||
private final void checkEncoding(ZipCoder zc, byte[] a, int pos, int nlen) throws ZipException {
|
||||
try {
|
||||
zc.toString(a, pos, nlen);
|
||||
} catch(Exception e) {
|
||||
zerror("invalid CEN header (bad entry name)");
|
||||
}
|
||||
}
|
||||
|
||||
private static final int hashN(byte[] a, int off, int len) {
|
||||
int h = 1;
|
||||
while (len-- > 0) {
|
||||
h = 31 * h + a[off++];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private static final int hash_append(int hash, byte b) {
|
||||
return hash * 31 + b;
|
||||
}
|
||||
|
||||
private static class End {
|
||||
int centot; // 4 bytes
|
||||
long cenlen; // 4 bytes
|
||||
|
@ -1489,12 +1526,18 @@ public class ZipFile implements ZipConstants, Closeable {
|
|||
int nlen = CENNAM(cen, pos);
|
||||
int elen = CENEXT(cen, pos);
|
||||
int clen = CENCOM(cen, pos);
|
||||
if ((CENFLG(cen, pos) & 1) != 0)
|
||||
int flag = CENFLG(cen, pos);
|
||||
if ((flag & 1) != 0)
|
||||
zerror("invalid CEN header (encrypted entry)");
|
||||
if (method != STORED && method != DEFLATED)
|
||||
zerror("invalid CEN header (bad compression method: " + method + ")");
|
||||
if (entryPos + nlen > limit)
|
||||
zerror("invalid CEN header (bad header size)");
|
||||
if (zc.isUTF8() || (flag & USE_UTF8) != 0) {
|
||||
checkUTF8(cen, pos + CENHDR, nlen);
|
||||
} else {
|
||||
checkEncoding(zc, cen, pos + CENHDR, nlen);
|
||||
}
|
||||
// Record the CEN offset and the name hash in our hash cell.
|
||||
hash = zipCoderForPos(pos).normalizedHash(cen, entryPos, nlen);
|
||||
hsh = (hash & 0x7fffffff) % tablelen;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2020, 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
|
||||
|
@ -298,7 +298,7 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants
|
|||
readFully(b, 0, len);
|
||||
// Force to use UTF-8 if the USE_UTF8 bit is ON
|
||||
ZipEntry e = createZipEntry(((flag & USE_UTF8) != 0)
|
||||
? zc.toStringUTF8(b, len)
|
||||
? ZipCoder.toStringUTF8(b, len)
|
||||
: zc.toString(b, len));
|
||||
// now get the remaining fields for the entry
|
||||
if ((flag & 1) == 1) {
|
||||
|
|
|
@ -186,7 +186,7 @@ public final class Punycode {
|
|||
for(j=0; j<srcLength; ++j) {
|
||||
if(srcCPCount==MAX_CP_COUNT) {
|
||||
/* too many input code points */
|
||||
throw new IndexOutOfBoundsException();
|
||||
throw new ParseException("Too many input code points", -1);
|
||||
}
|
||||
c=src.charAt(j);
|
||||
if(isBasic(c)) {
|
||||
|
|
|
@ -116,6 +116,9 @@ public class ContentInfo {
|
|||
DerValue[] contents;
|
||||
|
||||
typeAndContent = derin.getSequence(2);
|
||||
if (typeAndContent.length < 1 || typeAndContent.length > 2) {
|
||||
throw new ParsingException("Invalid length for ContentInfo");
|
||||
}
|
||||
|
||||
// Parse the content type
|
||||
type = typeAndContent[0];
|
||||
|
@ -135,6 +138,9 @@ public class ContentInfo {
|
|||
disTaggedContent
|
||||
= new DerInputStream(taggedContent.toByteArray());
|
||||
contents = disTaggedContent.getSet(1, true);
|
||||
if (contents.length != 1) {
|
||||
throw new ParsingException("ContentInfo encoding error");
|
||||
}
|
||||
content = contents[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2020, 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
|
||||
|
@ -144,6 +144,9 @@ public class SignerInfo implements DerEncoder {
|
|||
|
||||
// issuerAndSerialNumber
|
||||
DerValue[] issuerAndSerialNumber = derin.getSequence(2);
|
||||
if (issuerAndSerialNumber.length != 2) {
|
||||
throw new ParsingException("Invalid length for IssuerAndSerialNumber");
|
||||
}
|
||||
byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray();
|
||||
issuerName = new X500Name(new DerValue(DerValue.tag_Sequence,
|
||||
issuerBytes));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2020, 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
|
||||
|
@ -59,10 +59,16 @@ class MacData {
|
|||
throws IOException, ParsingException
|
||||
{
|
||||
DerValue[] macData = derin.getSequence(2);
|
||||
if (macData.length < 2 || macData.length > 3) {
|
||||
throw new ParsingException("Invalid length for MacData");
|
||||
}
|
||||
|
||||
// Parse the digest info
|
||||
DerInputStream digestIn = new DerInputStream(macData[0].toByteArray());
|
||||
DerValue[] digestInfo = digestIn.getSequence(2);
|
||||
if (digestInfo.length != 2) {
|
||||
throw new ParsingException("Invalid length for DigestInfo");
|
||||
}
|
||||
|
||||
// Parse the DigestAlgorithmIdentifier.
|
||||
AlgorithmId digestAlgorithmId = AlgorithmId.parse(digestInfo[0]);
|
||||
|
|
|
@ -383,6 +383,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||
DerInputStream in = val.toDerInputStream();
|
||||
int i = in.getInteger();
|
||||
DerValue[] value = in.getSequence(2);
|
||||
if (value.length < 1 || value.length > 2) {
|
||||
throw new IOException("Invalid length for AlgorithmIdentifier");
|
||||
}
|
||||
AlgorithmId algId = new AlgorithmId(value[0].getOID());
|
||||
String keyAlgo = algId.getName();
|
||||
|
||||
|
@ -2034,11 +2037,17 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||
DerInputStream edi =
|
||||
safeContents.getContent().toDerInputStream();
|
||||
int edVersion = edi.getInteger();
|
||||
DerValue[] seq = edi.getSequence(2);
|
||||
DerValue[] seq = edi.getSequence(3);
|
||||
if (seq.length != 3) {
|
||||
// We require the encryptedContent field, even though
|
||||
// it is optional
|
||||
throw new IOException("Invalid length for EncryptedContentInfo");
|
||||
}
|
||||
ObjectIdentifier edContentType = seq[0].getOID();
|
||||
eAlgId = seq[1].toByteArray();
|
||||
if (!seq[2].isContextSpecific((byte)0)) {
|
||||
throw new IOException("encrypted content not present!");
|
||||
throw new IOException("unsupported encrypted content type "
|
||||
+ seq[2].tag);
|
||||
}
|
||||
byte newTag = DerValue.tag_OctetString;
|
||||
if (seq[2].isConstructed())
|
||||
|
@ -2379,6 +2388,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||
} else if (bagId.equals(CertBag_OID)) {
|
||||
DerInputStream cs = new DerInputStream(bagValue.toByteArray());
|
||||
DerValue[] certValues = cs.getSequence(2);
|
||||
if (certValues.length != 2) {
|
||||
throw new IOException("Invalid length for CertBag");
|
||||
}
|
||||
ObjectIdentifier certId = certValues[0].getOID();
|
||||
if (!certValues[1].isContextSpecific((byte)0)) {
|
||||
throw new IOException("unsupported PKCS12 cert value type "
|
||||
|
@ -2394,6 +2406,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||
} else if (bagId.equals(SecretBag_OID)) {
|
||||
DerInputStream ss = new DerInputStream(bagValue.toByteArray());
|
||||
DerValue[] secretValues = ss.getSequence(2);
|
||||
if (secretValues.length != 2) {
|
||||
throw new IOException("Invalid length for SecretBag");
|
||||
}
|
||||
ObjectIdentifier secretId = secretValues[0].getOID();
|
||||
if (!secretValues[1].isContextSpecific((byte)0)) {
|
||||
throw new IOException(
|
||||
|
@ -2432,6 +2447,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||
byte[] encoded = attrSet[j].toByteArray();
|
||||
DerInputStream as = new DerInputStream(encoded);
|
||||
DerValue[] attrSeq = as.getSequence(2);
|
||||
if (attrSeq.length != 2) {
|
||||
throw new IOException("Invalid length for Attribute");
|
||||
}
|
||||
ObjectIdentifier attrId = attrSeq[0].getOID();
|
||||
DerInputStream vs =
|
||||
new DerInputStream(attrSeq[1].toByteArray());
|
||||
|
|
|
@ -258,7 +258,7 @@ public final class OCSPResponse {
|
|||
DerInputStream basicOCSPResponse =
|
||||
new DerInputStream(derIn.getOctetString());
|
||||
|
||||
DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
|
||||
DerValue[] seqTmp = basicOCSPResponse.getSequence(3);
|
||||
if (seqTmp.length < 3) {
|
||||
throw new IOException("Unexpected BasicOCSPResponse value");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2020, 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
|
||||
|
@ -312,15 +312,15 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
|
||||
if (generalized) {
|
||||
type = "Generalized";
|
||||
year = 1000 * Character.digit((char)buf[pos++], 10);
|
||||
year += 100 * Character.digit((char)buf[pos++], 10);
|
||||
year += 10 * Character.digit((char)buf[pos++], 10);
|
||||
year += Character.digit((char)buf[pos++], 10);
|
||||
year = 1000 * toDigit(buf[pos++], type);
|
||||
year += 100 * toDigit(buf[pos++], type);
|
||||
year += 10 * toDigit(buf[pos++], type);
|
||||
year += toDigit(buf[pos++], type);
|
||||
len -= 2; // For the two extra YY
|
||||
} else {
|
||||
type = "UTC";
|
||||
year = 10 * Character.digit((char)buf[pos++], 10);
|
||||
year += Character.digit((char)buf[pos++], 10);
|
||||
year = 10 * toDigit(buf[pos++], type);
|
||||
year += toDigit(buf[pos++], type);
|
||||
|
||||
if (year < 50) // origin 2000
|
||||
year += 2000;
|
||||
|
@ -328,17 +328,17 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
year += 1900; // origin 1900
|
||||
}
|
||||
|
||||
month = 10 * Character.digit((char)buf[pos++], 10);
|
||||
month += Character.digit((char)buf[pos++], 10);
|
||||
month = 10 * toDigit(buf[pos++], type);
|
||||
month += toDigit(buf[pos++], type);
|
||||
|
||||
day = 10 * Character.digit((char)buf[pos++], 10);
|
||||
day += Character.digit((char)buf[pos++], 10);
|
||||
day = 10 * toDigit(buf[pos++], type);
|
||||
day += toDigit(buf[pos++], type);
|
||||
|
||||
hour = 10 * Character.digit((char)buf[pos++], 10);
|
||||
hour += Character.digit((char)buf[pos++], 10);
|
||||
hour = 10 * toDigit(buf[pos++], type);
|
||||
hour += toDigit(buf[pos++], type);
|
||||
|
||||
minute = 10 * Character.digit((char)buf[pos++], 10);
|
||||
minute += Character.digit((char)buf[pos++], 10);
|
||||
minute = 10 * toDigit(buf[pos++], type);
|
||||
minute += toDigit(buf[pos++], type);
|
||||
|
||||
len -= 10; // YYMMDDhhmm
|
||||
|
||||
|
@ -350,12 +350,16 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
|
||||
millis = 0;
|
||||
if (len > 2) {
|
||||
second = 10 * Character.digit((char)buf[pos++], 10);
|
||||
second += Character.digit((char)buf[pos++], 10);
|
||||
second = 10 * toDigit(buf[pos++], type);
|
||||
second += toDigit(buf[pos++], type);
|
||||
len -= 2;
|
||||
// handle fractional seconds (if present)
|
||||
if (buf[pos] == '.' || buf[pos] == ',') {
|
||||
if (generalized && (buf[pos] == '.' || buf[pos] == ',')) {
|
||||
len --;
|
||||
if (len == 0) {
|
||||
throw new IOException("Parse " + type +
|
||||
" time, empty fractional part");
|
||||
}
|
||||
pos++;
|
||||
int precision = 0;
|
||||
while (buf[pos] != 'Z' &&
|
||||
|
@ -363,8 +367,13 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
buf[pos] != '-') {
|
||||
// Validate all digits in the fractional part but
|
||||
// store millisecond precision only
|
||||
int thisDigit = Character.digit((char)buf[pos], 10);
|
||||
int thisDigit = toDigit(buf[pos], type);
|
||||
precision++;
|
||||
len--;
|
||||
if (len == 0) {
|
||||
throw new IOException("Parse " + type +
|
||||
" time, invalid fractional part");
|
||||
}
|
||||
pos++;
|
||||
switch (precision) {
|
||||
case 1:
|
||||
|
@ -382,7 +391,6 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
throw new IOException("Parse " + type +
|
||||
" time, empty fractional part");
|
||||
}
|
||||
len -= precision;
|
||||
}
|
||||
} else
|
||||
second = 0;
|
||||
|
@ -412,10 +420,13 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
|
||||
switch (buf[pos++]) {
|
||||
case '+':
|
||||
hr = 10 * Character.digit((char)buf[pos++], 10);
|
||||
hr += Character.digit((char)buf[pos++], 10);
|
||||
min = 10 * Character.digit((char)buf[pos++], 10);
|
||||
min += Character.digit((char)buf[pos++], 10);
|
||||
if (len != 5) {
|
||||
throw new IOException("Parse " + type + " time, invalid offset");
|
||||
}
|
||||
hr = 10 * toDigit(buf[pos++], type);
|
||||
hr += toDigit(buf[pos++], type);
|
||||
min = 10 * toDigit(buf[pos++], type);
|
||||
min += toDigit(buf[pos++], type);
|
||||
|
||||
if (hr >= 24 || min >= 60)
|
||||
throw new IOException("Parse " + type + " time, +hhmm");
|
||||
|
@ -424,10 +435,13 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
break;
|
||||
|
||||
case '-':
|
||||
hr = 10 * Character.digit((char)buf[pos++], 10);
|
||||
hr += Character.digit((char)buf[pos++], 10);
|
||||
min = 10 * Character.digit((char)buf[pos++], 10);
|
||||
min += Character.digit((char)buf[pos++], 10);
|
||||
if (len != 5) {
|
||||
throw new IOException("Parse " + type + " time, invalid offset");
|
||||
}
|
||||
hr = 10 * toDigit(buf[pos++], type);
|
||||
hr += toDigit(buf[pos++], type);
|
||||
min = 10 * toDigit(buf[pos++], type);
|
||||
min += toDigit(buf[pos++], type);
|
||||
|
||||
if (hr >= 24 || min >= 60)
|
||||
throw new IOException("Parse " + type + " time, -hhmm");
|
||||
|
@ -436,6 +450,9 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
break;
|
||||
|
||||
case 'Z':
|
||||
if (len != 1) {
|
||||
throw new IOException("Parse " + type + " time, invalid format");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -443,4 +460,16 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
|
|||
}
|
||||
return new Date(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts byte (represented as a char) to int.
|
||||
* @throws IOException if integer is not a valid digit in the specified
|
||||
* radix (10)
|
||||
*/
|
||||
private static int toDigit(byte b, String type) throws IOException {
|
||||
if (b < '0' || b > '9') {
|
||||
throw new IOException("Parse " + type + " time, invalid format");
|
||||
}
|
||||
return b - '0';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, 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
|
||||
|
@ -31,6 +31,7 @@ import java.net.InetAddress;
|
|||
import java.net.UnknownHostException;
|
||||
import java.security.Principal;
|
||||
import java.security.cert.*;
|
||||
import java.text.Normalizer;
|
||||
import java.util.*;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import javax.net.ssl.SNIHostName;
|
||||
|
@ -217,8 +218,12 @@ public class HostnameChecker {
|
|||
(X500Name.commonName_oid);
|
||||
if (derValue != null) {
|
||||
try {
|
||||
if (isMatched(expectedName, derValue.getAsString(),
|
||||
chainsToPublicCA)) {
|
||||
String cname = derValue.getAsString();
|
||||
if (!Normalizer.isNormalized(cname, Normalizer.Form.NFKC)) {
|
||||
throw new CertificateException("Not a formal name "
|
||||
+ cname);
|
||||
}
|
||||
if (isMatched(expectedName, cname, chainsToPublicCA)) {
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -52,6 +52,25 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
*/
|
||||
|
||||
public final class ObjectIdentifier implements Serializable {
|
||||
/*
|
||||
* The maximum encoded OID length, excluding the ASN.1 encoding tag and
|
||||
* length.
|
||||
*
|
||||
* In theory, there is no maximum size for OIDs. However, there are some
|
||||
* limitation in practice.
|
||||
*
|
||||
* RFC 5280 mandates support for OIDs that have arc elements with values
|
||||
* that are less than 2^28 (that is, they MUST be between 0 and
|
||||
* 268,435,455, inclusive), and implementations MUST be able to handle
|
||||
* OIDs with up to 20 elements (inclusive). Per RFC 5280, an encoded
|
||||
* OID should be less than 80 bytes for safe interoperability.
|
||||
*
|
||||
* This class could be used for protocols other than X.509 certificates.
|
||||
* To be safe, a relatively large but still reasonable value is chosen
|
||||
* as the restriction in JDK.
|
||||
*/
|
||||
private static final int MAXIMUM_OID_SIZE = 4096; // 2^12
|
||||
|
||||
/**
|
||||
* We use the DER value (no tag, no length) as the internal format
|
||||
* @serial
|
||||
|
@ -118,7 +137,13 @@ public final class ObjectIdentifier implements Serializable {
|
|||
if (componentLen > comp.length) {
|
||||
componentLen = comp.length;
|
||||
}
|
||||
|
||||
// Check the estimated size before it is too later.
|
||||
checkOidSize(componentLen);
|
||||
|
||||
init(comp, componentLen);
|
||||
} else {
|
||||
checkOidSize(encoding.length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,6 +228,8 @@ public final class ObjectIdentifier implements Serializable {
|
|||
}
|
||||
start = end + 1;
|
||||
count++;
|
||||
|
||||
checkOidSize(pos);
|
||||
} while (end != -1);
|
||||
|
||||
checkCount(count);
|
||||
|
@ -250,11 +277,13 @@ public final class ObjectIdentifier implements Serializable {
|
|||
);
|
||||
|
||||
int len = in.getDefiniteLength();
|
||||
checkOidSize(len);
|
||||
if (len > in.available()) {
|
||||
throw new IOException("ObjectIdentifier() -- length exceeds" +
|
||||
throw new IOException("ObjectIdentifier length exceeds " +
|
||||
"data available. Length: " + len + ", Available: " +
|
||||
in.available());
|
||||
}
|
||||
|
||||
encoding = new byte[len];
|
||||
in.getBytes(encoding);
|
||||
check(encoding);
|
||||
|
@ -267,26 +296,32 @@ public final class ObjectIdentifier implements Serializable {
|
|||
*/
|
||||
ObjectIdentifier(DerInputBuffer buf) throws IOException {
|
||||
DerInputStream in = new DerInputStream(buf);
|
||||
encoding = new byte[in.available()];
|
||||
int len = in.available();
|
||||
checkOidSize(len);
|
||||
|
||||
encoding = new byte[len];
|
||||
in.getBytes(encoding);
|
||||
check(encoding);
|
||||
}
|
||||
|
||||
private void init(int[] components, int length) {
|
||||
private void init(int[] components, int length) throws IOException {
|
||||
int pos = 0;
|
||||
byte[] tmp = new byte[length*5+1]; // +1 for empty input
|
||||
byte[] tmp = new byte[length * 5 + 1]; // +1 for empty input
|
||||
|
||||
if (components[1] < Integer.MAX_VALUE - components[0]*40)
|
||||
pos += pack7Oid(components[0]*40+components[1], tmp, pos);
|
||||
else {
|
||||
if (components[1] < Integer.MAX_VALUE - components[0] * 40) {
|
||||
pos += pack7Oid(components[0] * 40 + components[1], tmp, pos);
|
||||
} else {
|
||||
BigInteger big = BigInteger.valueOf(components[1]);
|
||||
big = big.add(BigInteger.valueOf(components[0]*40));
|
||||
big = big.add(BigInteger.valueOf(components[0] * 40));
|
||||
pos += pack7Oid(big, tmp, pos);
|
||||
}
|
||||
|
||||
for (int i=2; i<length; i++) {
|
||||
for (int i = 2; i < length; i++) {
|
||||
pos += pack7Oid(components[i], tmp, pos);
|
||||
|
||||
checkOidSize(pos);
|
||||
}
|
||||
|
||||
encoding = new byte[pos];
|
||||
System.arraycopy(tmp, 0, encoding, 0, pos);
|
||||
}
|
||||
|
@ -690,4 +725,13 @@ public final class ObjectIdentifier implements Serializable {
|
|||
"oid component #" + (i+1) + " must be non-negative ");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkOidSize(int oidLength) throws IOException {
|
||||
if (oidLength > MAXIMUM_OID_SIZE) {
|
||||
throw new IOException(
|
||||
"ObjectIdentifier encoded length exceeds " +
|
||||
"the restriction in JDK (OId length(>=): " + oidLength +
|
||||
", Restriction: " + MAXIMUM_OID_SIZE + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue