This commit is contained in:
Jesper Wilhelmsson 2022-01-20 01:18:38 +00:00
commit 4616c13c2f
67 changed files with 1126 additions and 799 deletions

View file

@ -177,6 +177,10 @@ final class KeyProtector {
byte[] encodedParams =
encrInfo.getAlgorithm().getEncodedParams();
if (encodedParams == null) {
throw new IOException("Missing PBE parameters");
}
// parse the PBE parameters into the corresponding spec
AlgorithmParameters pbeParams =
AlgorithmParameters.getInstance("PBE");

View file

@ -107,8 +107,12 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals(OID_MGF1)) {
throw new IOException("Only MGF1 mgf is supported");
}
byte[] encodedParams = val.getEncodedParams();
if (encodedParams == null) {
throw new IOException("Missing MGF1 parameters");
}
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
new DerValue(encodedParams));
mgfSpec = switch (params.getName()) {
case "SHA-1" -> MGF1ParameterSpec.SHA1;
case "SHA-224" -> MGF1ParameterSpec.SHA224;
@ -129,7 +133,12 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals(OID_PSpecified)) {
throw new IOException("Wrong OID for pSpecified");
}
p = DerValue.wrap(val.getEncodedParams()).getOctetString();
byte[] encodedParams = val.getEncodedParams();
if (encodedParams == null) {
throw new IOException("Missing pSpecified label");
}
p = DerValue.wrap(encodedParams).getOctetString();
} else {
p = new byte[0];
}

View file

@ -1315,6 +1315,8 @@ public class ObjectInputStream
* <li>each object reference previously deserialized from the stream
* (class is {@code null}, arrayLength is -1),
* <li>each regular class (class is not {@code null}, arrayLength is -1),
* <li>each interface class explicitly referenced in the stream
* (it is not called for interfaces implemented by classes in the stream),
* <li>each interface of a dynamic proxy and the dynamic proxy class itself
* (class is not {@code null}, arrayLength is -1),
* <li>each array is filtered using the array type and length of the array
@ -2071,6 +2073,30 @@ public class ObjectInputStream
totalObjectRefs++;
depth++;
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
if (cl != null) {
// Check that serial filtering has been done on the local class descriptor's superclass,
// in case it does not appear in the stream.
// Find the next super descriptor that has a local class descriptor.
// Descriptors for which there is no local class are ignored.
ObjectStreamClass superLocal = null;
for (ObjectStreamClass sDesc = desc.getSuperDesc(); sDesc != null; sDesc = sDesc.getSuperDesc()) {
if ((superLocal = sDesc.getLocalDesc()) != null) {
break;
}
}
// Scan local descriptor superclasses for a match with the local descriptor of the super found above.
// For each super descriptor before the match, invoke the serial filter on the class.
// The filter is invoked for each class that has not already been filtered
// but would be filtered if the instance had been serialized by this Java runtime.
for (ObjectStreamClass lDesc = desc.getLocalDesc().getSuperDesc();
lDesc != null && lDesc != superLocal;
lDesc = lDesc.getSuperDesc()) {
filterCheck(lDesc.forClass(), -1);
}
}
} finally {
depth--;
}
@ -2529,6 +2555,13 @@ public class ObjectInputStream
throw new InternalError();
}
clear();
// Check that an object follows the TC_EXCEPTION typecode
byte tc = bin.peekByte();
if (tc != TC_OBJECT &&
tc != TC_REFERENCE) {
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
return (IOException) readObject0(Object.class, false);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2021, 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
@ -26,7 +26,12 @@
package java.lang;
import java.io.IOException;
import java.util.Arrays;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serial;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import jdk.internal.vm.annotation.IntrinsicCandidate;
/**
@ -106,7 +111,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
*/
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
implements Serializable, Comparable<StringBuffer>, CharSequence
{
/**
@ -116,7 +121,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
private transient String toStringCache;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
@java.io.Serial
@Serial
static final long serialVersionUID = 3388685877147921107L;
/**
@ -725,25 +730,25 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* A flag indicating whether the backing array is shared.
* The value is ignored upon deserialization.
*/
@java.io.Serial
private static final java.io.ObjectStreamField[] serialPersistentFields =
@Serial
private static final ObjectStreamField[] serialPersistentFields =
{
new java.io.ObjectStreamField("value", char[].class),
new java.io.ObjectStreamField("count", Integer.TYPE),
new java.io.ObjectStreamField("shared", Boolean.TYPE),
new ObjectStreamField("value", char[].class),
new ObjectStreamField("count", Integer.TYPE),
new ObjectStreamField("shared", Boolean.TYPE),
};
/**
* The {@code writeObject} method is called to write the state of the {@code StringBuffer} to
* a stream.
* The {@code writeObject} method is called to write the state of the
* {@code StringBuffer} to a stream.
*
* @param s the {@code ObjectOutputStream} to which data is written
* @throws IOException if an I/O error occurs
*/
@java.io.Serial
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
@Serial
private synchronized void writeObject(ObjectOutputStream s)
throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
char[] val = new char[capacity()];
if (isLatin1()) {
StringLatin1.getChars(value, 0, count, val, 0);
@ -757,20 +762,26 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
}
/**
* The {@code readObject} method is called to restore the state of the {@code StringBuffer} from
* a stream.
* The {@code readObject} method is called to restore the state of the
* {@code StringBuffer} from a stream.
*
* @param s the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields();
@Serial
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
char[] val = (char[])fields.get("value", null);
int c = fields.get("count", 0);
if (c < 0 || c > val.length) {
throw new StreamCorruptedException("count value invalid");
}
initBytes(val, 0, val.length);
count = fields.get("count", 0);
count = c;
// ignore shared field
}
synchronized void getBytes(byte[] dst, int dstBegin, byte coder) {

View file

@ -28,6 +28,10 @@ package java.lang;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.StreamCorruptedException;
/**
* A mutable sequence of characters. This class provides an API compatible
@ -90,7 +94,7 @@ public final class StringBuilder
{
/** use serialVersionUID for interoperability */
@java.io.Serial
@Serial
static final long serialVersionUID = 4383685877147921099L;
/**
@ -464,9 +468,8 @@ public final class StringBuilder
* @param s the {@code ObjectOutputStream} to which data is written
* @throws IOException if an I/O error occurs
*/
@java.io.Serial
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@Serial
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeInt(count);
char[] val = new char[capacity()];
@ -486,13 +489,16 @@ public final class StringBuilder
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
@Serial
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
count = s.readInt();
int c = s.readInt();
char[] val = (char[]) s.readObject();
if (c < 0 || c > val.length) {
throw new StreamCorruptedException("count value invalid");
}
initBytes(val, 0, val.length);
count = c;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2021, 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
@ -1254,7 +1254,7 @@ public class Hashtable<K,V>
* Reconstitute the Hashtable from a stream (i.e., deserialize it).
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
readHashtable(s);
}
@ -1263,14 +1263,16 @@ public class Hashtable<K,V>
* Perform deserialization of the Hashtable from an ObjectInputStream.
* The Properties class overrides this method.
*/
void readHashtable(java.io.ObjectInputStream s)
void readHashtable(ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read in the threshold and loadFactor
s.defaultReadObject();
// Validate loadFactor (ignore threshold - it will be re-computed)
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new StreamCorruptedException("Illegal Load: " + loadFactor);
ObjectInputStream.GetField fields = s.readFields();
// Read and validate loadFactor (ignore threshold - it will be re-computed)
float lf = fields.get("loadFactor", 0.75f);
if (lf <= 0 || Float.isNaN(lf))
throw new StreamCorruptedException("Illegal load factor: " + lf);
lf = Math.min(Math.max(0.25f, lf), 4.0f);
// Read the original length of the array and number of elements
int origlength = s.readInt();
@ -1282,13 +1284,13 @@ public class Hashtable<K,V>
// Clamp original length to be more than elements / loadFactor
// (this is the invariant enforced with auto-growth)
origlength = Math.max(origlength, (int)(elements / loadFactor) + 1);
origlength = Math.max(origlength, (int)(elements / lf) + 1);
// Compute new length with a bit of room 5% + 3 to grow but
// no larger than the clamped original length. Make the length
// odd if it's large enough, this helps distribute the entries.
// Guard against the length ending up zero, that's not valid.
int length = (int)((elements + elements / 20) / loadFactor) + 3;
int length = (int)((elements + elements / 20) / lf) + 3;
if (length > elements && (length & 1) == 0)
length--;
length = Math.min(length, origlength);
@ -1300,8 +1302,9 @@ public class Hashtable<K,V>
// Check Map.Entry[].class since it's the nearest public type to
// what we're actually creating.
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, length);
Hashtable.UnsafeHolder.putLoadFactor(this, lf);
table = new Entry<?,?>[length];
threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
threshold = (int)Math.min(length * lf, MAX_ARRAY_SIZE + 1);
count = 0;
// Read the number of elements and then all the key/value objects
@ -1315,6 +1318,18 @@ public class Hashtable<K,V>
}
}
// Support for resetting final field during deserializing
private static final class UnsafeHolder {
private UnsafeHolder() { throw new InternalError(); }
private static final jdk.internal.misc.Unsafe unsafe
= jdk.internal.misc.Unsafe.getUnsafe();
private static final long LF_OFFSET
= unsafe.objectFieldOffset(Hashtable.class, "loadFactor");
static void putLoadFactor(Hashtable<?, ?> table, float lf) {
unsafe.putFloat(table, LF_OFFSET, lf);
}
}
/**
* The put method used by readObject. This is provided because put
* is overridable and should not be called in readObject since the

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@ -25,6 +25,8 @@
package java.util;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@ -1267,12 +1269,12 @@ public class IdentityHashMap<K,V>
* particular order.
*/
@java.io.Serial
private void writeObject(java.io.ObjectOutputStream s)
private void writeObject(ObjectOutputStream s)
throws java.io.IOException {
// Write out and any hidden stuff
// Write out size (number of mappings) and any hidden stuff
s.defaultWriteObject();
// Write out size (number of Mappings)
// Write out size again (maintained for backward compatibility)
s.writeInt(size);
// Write out keys and values (alternating)
@ -1291,18 +1293,20 @@ public class IdentityHashMap<K,V>
* deserializes it).
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
private void readObject(ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden stuff
s.defaultReadObject();
// Size (number of mappings) is written to the stream twice
// Read first size value and ignore it
s.readFields();
// Read in size (number of Mappings)
// Read second size value, validate and assign to size field
int size = s.readInt();
if (size < 0)
throw new java.io.StreamCorruptedException
("Illegal mappings count: " + size);
int cap = capacity(size);
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap);
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap*2);
this.size = size;
init(cap);
// Read the keys and values, and put the mappings in the table

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -25,6 +25,7 @@
package java.util.jar;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collection;
@ -366,7 +367,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
int read(Manifest.FastInputStream is, byte[] lbuf, String filename, int lineNumber) throws IOException {
String name = null, value;
byte[] lastline = null;
ByteArrayOutputStream fullLine = new ByteArrayOutputStream();
int len;
while ((len = is.readLine(lbuf)) != -1) {
@ -392,15 +393,12 @@ public class Attributes implements Map<Object,Object>, Cloneable {
+ Manifest.getErrorPosition(filename, lineNumber) + ")");
}
lineContinued = true;
byte[] buf = new byte[lastline.length + len - 1];
System.arraycopy(lastline, 0, buf, 0, lastline.length);
System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
fullLine.write(lbuf, 1, len - 1);
if (is.peek() == ' ') {
lastline = buf;
continue;
}
value = new String(buf, 0, buf.length, UTF_8.INSTANCE);
lastline = null;
value = fullLine.toString(UTF_8.INSTANCE);
fullLine.reset();
} else {
while (lbuf[i++] != ':') {
if (i >= len) {
@ -414,8 +412,8 @@ public class Attributes implements Map<Object,Object>, Cloneable {
}
name = new String(lbuf, 0, i - 2, UTF_8.INSTANCE);
if (is.peek() == ' ') {
lastline = new byte[len - i];
System.arraycopy(lbuf, i, lastline, 0, len - i);
fullLine.reset();
fullLine.write(lbuf, i, len - i);
continue;
}
value = new String(lbuf, i, len - i, UTF_8.INSTANCE);

View file

@ -3440,8 +3440,8 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
private static final int countChars(CharSequence seq, int index,
int lengthInCodePoints) {
// optimization
if (lengthInCodePoints == 1 && !Character.isHighSurrogate(seq.charAt(index))) {
assert (index >= 0 && index < seq.length());
if (lengthInCodePoints == 1 && index >= 0 && index < seq.length() &&
!Character.isHighSurrogate(seq.charAt(index))) {
return 1;
}
int length = seq.length();

View file

@ -77,15 +77,18 @@ public class EncryptedPrivateKeyInfo {
* @exception NullPointerException if the <code>encoded</code> is null.
* @exception IOException if error occurs when parsing the ASN.1 encoding.
*/
public EncryptedPrivateKeyInfo(byte[] encoded)
throws IOException {
public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException {
if (encoded == null) {
throw new NullPointerException("the encoded parameter " +
"must be non-null");
"must be non-null");
}
this.encoded = encoded.clone();
DerValue val = new DerValue(this.encoded);
DerValue val = new DerValue(encoded);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("DER header error: no SEQ tag");
}
this.encoded = encoded.clone();
DerValue[] seq = new DerValue[2];
seq[0] = val.data.getDerValue();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, 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
@ -127,7 +127,9 @@ public class ContentInfo {
if (oldStyle) {
// JDK1.1.x-style encoding
content = typeAndContent[1];
if (typeAndContent.length > 1) { // content is OPTIONAL
content = typeAndContent[1];
}
} else {
// This is the correct, standards-compliant encoding.
// Parse the content (OPTIONAL field).

View file

@ -383,8 +383,15 @@ public class SignerInfo implements DerEncoder {
if (digestAlgName.equals("SHAKE256")
|| digestAlgName.equals("SHAKE256-LEN")) {
if (digestAlgName.equals("SHAKE256-LEN")) {
int v = new DerValue(digestAlgorithmId
.getEncodedParams()).getInteger();
// RFC8419: for EdDSA in CMS, the id-shake256-len
// algorithm id must contain parameter value 512
// encoded as a positive integer value
byte[] params = digestAlgorithmId.getEncodedParams();
if (params == null) {
throw new SignatureException(
"id-shake256-len oid missing length");
}
int v = new DerValue(params).getInteger();
if (v != 512) {
throw new SignatureException(
"Unsupported id-shake256-" + v);
@ -527,6 +534,7 @@ public class SignerInfo implements DerEncoder {
if (spec == null) {
throw new NoSuchAlgorithmException("Missing PSSParameterSpec for RSASSA-PSS algorithm");
}
if (!AlgorithmId.get(spec.getDigestAlgorithm()).equals(digAlgId)) {
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
}

View file

@ -102,8 +102,13 @@ public final class PSSParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals(AlgorithmId.MGF1_oid)) {
throw new IOException("Only MGF1 mgf is supported");
}
byte[] encodedParams = val.getEncodedParams();
if (encodedParams == null) {
throw new IOException("Missing MGF1 parameters");
}
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
new DerValue(encodedParams));
String mgfDigestName = params.getName();
switch (mgfDigestName) {
case "SHA-1":