This commit is contained in:
Jesper Wilhelmsson 2020-01-16 04:09:50 +01:00
commit 51d5164ca2
102 changed files with 2027 additions and 937 deletions

View file

@ -35,6 +35,7 @@ import java.util.Optional;
import java.util.function.Function;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
/**
* Filter classes, array lengths, and graph metrics during deserialization.
@ -205,15 +206,17 @@ public interface ObjectInputFilter {
* <p>
* The filter is configured during the initialization of the {@code ObjectInputFilter.Config}
* class. For example, by calling {@link #getSerialFilter() Config.getSerialFilter}.
* If the system property {@systemProperty jdk.serialFilter} is defined, it is used
* to configure the filter.
* If the system property is not defined, and the {@link java.security.Security}
* property {@code jdk.serialFilter} is defined then it is used to configure the filter.
* Otherwise, the filter is not configured during initialization.
* If the system property {@systemProperty jdk.serialFilter} is defined on the command line,
* it is used to configure the filter.
* If the system property is not defined on the command line, and the
* {@link java.security.Security} property {@code jdk.serialFilter} is defined
* then it is used to configure the filter.
* Otherwise, the filter is not configured during initialization and
* can be set with {@link #setSerialFilter(ObjectInputFilter) Config.setSerialFilter}.
* Setting the {@code jdk.serialFilter} with {@link System#setProperty(String, String)
* System.setProperty} <em>does not set the filter</em>.
* The syntax for each property is the same as for the
* {@link #createFilter(String) createFilter} method.
* If a filter is not configured, it can be set with
* {@link #setSerialFilter(ObjectInputFilter) Config.setSerialFilter}.
*
* @since 9
*/
@ -256,7 +259,7 @@ public interface ObjectInputFilter {
static {
configuredFilter = AccessController
.doPrivileged((PrivilegedAction<ObjectInputFilter>) () -> {
String props = System.getProperty(SERIAL_FILTER_PROPNAME);
String props = StaticProperty.jdkSerialFilter();
if (props == null) {
props = Security.getProperty(SERIAL_FILTER_PROPNAME);
}

View file

@ -453,16 +453,50 @@ public class ObjectInputStream
* @throws IOException Any of the usual Input/Output related exceptions.
*/
public final Object readObject()
throws IOException, ClassNotFoundException {
return readObject(Object.class);
}
/**
* Reads a String and only a string.
*
* @return the String read
* @throws EOFException If end of file is reached.
* @throws IOException If other I/O error has occurred.
*/
private String readString() throws IOException {
try {
return (String) readObject(String.class);
} catch (ClassNotFoundException cnf) {
throw new IllegalStateException(cnf);
}
}
/**
* Internal method to read an object from the ObjectInputStream of the expected type.
* Called only from {@code readObject()} and {@code readString()}.
* Only {@code Object.class} and {@code String.class} are supported.
*
* @param type the type expected; either Object.class or String.class
* @return an object of the type
* @throws IOException Any of the usual Input/Output related exceptions.
* @throws ClassNotFoundException Class of a serialized object cannot be
* found.
*/
private final Object readObject(Class<?> type)
throws IOException, ClassNotFoundException
{
if (enableOverride) {
return readObjectOverride();
}
if (! (type == Object.class || type == String.class))
throw new AssertionError("internal error");
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(false);
Object obj = readObject0(type, false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
@ -557,7 +591,7 @@ public class ObjectInputStream
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(true);
Object obj = readObject0(Object.class, true);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
@ -1577,8 +1611,10 @@ public class ObjectInputStream
/**
* Underlying readObject implementation.
* @param type a type expected to be deserialized; non-null
* @param unshared true if the object can not be a reference to a shared object, otherwise false
*/
private Object readObject0(boolean unshared) throws IOException {
private Object readObject0(Class<?> type, boolean unshared) throws IOException {
boolean oldMode = bin.getBlockDataMode();
if (oldMode) {
int remain = bin.currentBlockRemaining();
@ -1610,13 +1646,20 @@ public class ObjectInputStream
return readNull();
case TC_REFERENCE:
return readHandle(unshared);
// check the type of the existing object
return type.cast(readHandle(unshared));
case TC_CLASS:
if (type == String.class) {
throw new ClassCastException("Cannot cast a class to java.lang.String");
}
return readClass(unshared);
case TC_CLASSDESC:
case TC_PROXYCLASSDESC:
if (type == String.class) {
throw new ClassCastException("Cannot cast a class to java.lang.String");
}
return readClassDesc(unshared);
case TC_STRING:
@ -1624,15 +1667,27 @@ public class ObjectInputStream
return checkResolve(readString(unshared));
case TC_ARRAY:
if (type == String.class) {
throw new ClassCastException("Cannot cast an array to java.lang.String");
}
return checkResolve(readArray(unshared));
case TC_ENUM:
if (type == String.class) {
throw new ClassCastException("Cannot cast an enum to java.lang.String");
}
return checkResolve(readEnum(unshared));
case TC_OBJECT:
if (type == String.class) {
throw new ClassCastException("Cannot cast an object to java.lang.String");
}
return checkResolve(readOrdinaryObject(unshared));
case TC_EXCEPTION:
if (type == String.class) {
throw new ClassCastException("Cannot cast an exception to java.lang.String");
}
IOException ex = readFatalException();
throw new WriteAbortedException("writing aborted", ex);
@ -2004,7 +2059,7 @@ public class ObjectInputStream
if (ccl == null) {
for (int i = 0; i < len; i++) {
readObject0(false);
readObject0(Object.class, false);
}
} else if (ccl.isPrimitive()) {
if (ccl == Integer.TYPE) {
@ -2029,7 +2084,7 @@ public class ObjectInputStream
} else {
Object[] oa = (Object[]) array;
for (int i = 0; i < len; i++) {
oa[i] = readObject0(false);
oa[i] = readObject0(Object.class, false);
handles.markDependency(arrayHandle, passHandle);
}
}
@ -2393,7 +2448,7 @@ public class ObjectInputStream
return;
default:
readObject0(false);
readObject0(Object.class, false);
break;
}
}
@ -2438,7 +2493,7 @@ public class ObjectInputStream
int numPrimFields = fields.length - objVals.length;
for (int i = 0; i < objVals.length; i++) {
ObjectStreamField f = fields[numPrimFields + i];
objVals[i] = readObject0(f.isUnshared());
objVals[i] = readObject0(Object.class, f.isUnshared());
if (f.getField() != null) {
handles.markDependency(objHandle, passHandle);
}
@ -2479,7 +2534,7 @@ public class ObjectInputStream
throw new InternalError();
}
clear();
return (IOException) readObject0(false);
return (IOException) readObject0(Object.class, false);
}
/**
@ -2601,7 +2656,7 @@ public class ObjectInputStream
int numPrimFields = fields.length - objVals.length;
for (int i = 0; i < objVals.length; i++) {
objVals[i] =
readObject0(fields[numPrimFields + i].isUnshared());
readObject0(Object.class, fields[numPrimFields + i].isUnshared());
objHandles[i] = passHandle;
}
passHandle = oldHandle;
@ -4090,6 +4145,7 @@ public class ObjectInputStream
static {
SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);
}
}

View file

@ -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
@ -2119,7 +2119,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// approximately a 15 digit approximation to the square
// root, it is helpful to instead normalize this so that
// the significand portion is to right of the decimal
// point by roughly (scale() - precision() +1).
// point by roughly (scale() - precision() + 1).
// Now the precision / scale adjustment
int scaleAdjust = 0;
@ -2147,7 +2147,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// than 15 digits were needed, it might be faster to do
// the loop entirely in BigDecimal arithmetic.
//
// (A double value might have as much many as 17 decimal
// (A double value might have as many as 17 decimal
// digits of precision; it depends on the relative density
// of binary and decimal numbers at different regions of
// the number line.)
@ -2171,7 +2171,25 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if (originalPrecision == 0) {
targetPrecision = stripped.precision()/2 + 1;
} else {
targetPrecision = originalPrecision;
/*
* To avoid the need for post-Newton fix-up logic, in
* the case of half-way rounding modes, double the
* target precision so that the "2p + 2" property can
* be relied on to accomplish the final rounding.
*/
switch (mc.getRoundingMode()) {
case HALF_UP:
case HALF_DOWN:
case HALF_EVEN:
targetPrecision = 2 * originalPrecision;
if (targetPrecision < 0) // Overflow
targetPrecision = Integer.MAX_VALUE - 2;
break;
default:
targetPrecision = originalPrecision;
break;
}
}
// When setting the precision to use inside the Newton
@ -2199,33 +2217,81 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// If result*result != this numerically, the square
// root isn't exact
if (this.subtract(result.multiply(result)).compareTo(ZERO) != 0) {
if (this.subtract(result.square()).compareTo(ZERO) != 0) {
throw new ArithmeticException("Computed square root not exact.");
}
} else {
result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
switch (targetRm) {
case DOWN:
case FLOOR:
// Check if too big
if (result.square().compareTo(this) > 0) {
BigDecimal ulp = result.ulp();
// Adjust increment down in case of 1.0 = 10^0
// since the next smaller number is only 1/10
// as far way as the next larger at exponent
// boundaries. Test approx and *not* result to
// avoid having to detect an arbitrary power
// of ten.
if (approx.compareTo(ONE) == 0) {
ulp = ulp.multiply(ONE_TENTH);
}
result = result.subtract(ulp);
}
break;
case UP:
case CEILING:
// Check if too small
if (result.square().compareTo(this) < 0) {
result = result.add(result.ulp());
}
break;
default:
// No additional work, rely on "2p + 2" property
// for correct rounding. Alternatively, could
// instead run the Newton iteration to around p
// digits and then do tests and fix-ups on the
// rounded value. One possible set of tests and
// fix-ups is given in the Hull and Abrham paper;
// however, additional half-way cases can occur
// for BigDecimal given the more varied
// combinations of input and output precisions
// supported.
break;
}
}
// Test numerical properties at full precision before any
// scale adjustments.
assert squareRootResultAssertions(result, mc);
if (result.scale() != preferredScale) {
// The preferred scale of an add is
// max(addend.scale(), augend.scale()). Therefore, if
// the scale of the result is first minimized using
// stripTrailingZeros(), adding a zero of the
// preferred scale rounding the correct precision will
// perform the proper scale vs precision tradeoffs.
// preferred scale rounding to the correct precision
// will perform the proper scale vs precision
// tradeoffs.
result = result.stripTrailingZeros().
add(zeroWithFinalPreferredScale,
new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
}
assert squareRootResultAssertions(result, mc);
return result;
} else {
BigDecimal result = null;
switch (signum) {
case -1:
throw new ArithmeticException("Attempted square root " +
"of negative BigDecimal");
case 0:
return valueOf(0L, scale()/2);
result = valueOf(0L, scale()/2);
assert squareRootResultAssertions(result, mc);
return result;
default:
throw new AssertionError("Bad value from signum");
@ -2233,6 +2299,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
private BigDecimal square() {
return this.multiply(this);
}
private boolean isPowerOfTen() {
return BigInteger.ONE.equals(this.unscaledValue());
}
@ -2241,10 +2311,16 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* For nonzero values, check numerical correctness properties of
* the computed result for the chosen rounding mode.
*
* For the directed roundings, for DOWN and FLOOR, result^2 must
* be {@code <=} the input and (result+ulp)^2 must be {@code >} the
* input. Conversely, for UP and CEIL, result^2 must be {@code >=} the
* input and (result-ulp)^2 must be {@code <} the input.
* For the directed rounding modes:
*
* <ul>
*
* <li> For DOWN and FLOOR, result^2 must be {@code <=} the input
* and (result+ulp)^2 must be {@code >} the input.
*
* <li>Conversely, for UP and CEIL, result^2 must be {@code >=}
* the input and (result-ulp)^2 must be {@code <} the input.
* </ul>
*/
private boolean squareRootResultAssertions(BigDecimal result, MathContext mc) {
if (result.signum() == 0) {
@ -2254,52 +2330,68 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
BigDecimal ulp = result.ulp();
BigDecimal neighborUp = result.add(ulp);
// Make neighbor down accurate even for powers of ten
if (this.isPowerOfTen()) {
if (result.isPowerOfTen()) {
ulp = ulp.divide(TEN);
}
BigDecimal neighborDown = result.subtract(ulp);
// Both the starting value and result should be nonzero and positive.
if (result.signum() != 1 ||
this.signum() != 1) {
return false;
}
assert (result.signum() == 1 &&
this.signum() == 1) :
"Bad signum of this and/or its sqrt.";
switch (rm) {
case DOWN:
case FLOOR:
return
result.multiply(result).compareTo(this) <= 0 &&
neighborUp.multiply(neighborUp).compareTo(this) > 0;
assert
result.square().compareTo(this) <= 0 &&
neighborUp.square().compareTo(this) > 0:
"Square of result out for bounds rounding " + rm;
return true;
case UP:
case CEILING:
return
result.multiply(result).compareTo(this) >= 0 &&
neighborDown.multiply(neighborDown).compareTo(this) < 0;
assert
result.square().compareTo(this) >= 0 &&
neighborDown.square().compareTo(this) < 0:
"Square of result out for bounds rounding " + rm;
return true;
case HALF_DOWN:
case HALF_EVEN:
case HALF_UP:
BigDecimal err = result.multiply(result).subtract(this).abs();
BigDecimal errUp = neighborUp.multiply(neighborUp).subtract(this);
BigDecimal errDown = this.subtract(neighborDown.multiply(neighborDown));
BigDecimal err = result.square().subtract(this).abs();
BigDecimal errUp = neighborUp.square().subtract(this);
BigDecimal errDown = this.subtract(neighborDown.square());
// All error values should be positive so don't need to
// compare absolute values.
int err_comp_errUp = err.compareTo(errUp);
int err_comp_errDown = err.compareTo(errDown);
return
assert
errUp.signum() == 1 &&
errDown.signum() == 1 &&
errDown.signum() == 1 :
"Errors of neighbors squared don't have correct signs";
err_comp_errUp <= 0 &&
err_comp_errDown <= 0 &&
// For breaking a half-way tie, the return value may
// have a larger error than one of the neighbors. For
// example, the square root of 2.25 to a precision of
// 1 digit is either 1 or 2 depending on how the exact
// value of 1.5 is rounded. If 2 is returned, it will
// have a larger rounding error than its neighbor 1.
assert
err_comp_errUp <= 0 ||
err_comp_errDown <= 0 :
"Computed square root has larger error than neighbors for " + rm;
assert
((err_comp_errUp == 0 ) ? err_comp_errDown < 0 : true) &&
((err_comp_errDown == 0 ) ? err_comp_errUp < 0 : true);
((err_comp_errDown == 0 ) ? err_comp_errUp < 0 : true) :
"Incorrect error relationships";
// && could check for digit conditions for ties too
return true;
default: // Definition of UNNECESSARY already verified.
return true;

View file

@ -97,7 +97,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
fd = new FileDescriptor();
try {
datagramSocketCreate();
SocketCleanable.register(fd);
SocketCleanable.register(fd, false);
} catch (SocketException ioe) {
ResourceManager.afterUdpClose();
fd = null;

View file

@ -127,7 +127,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
fd = new FileDescriptor();
try {
socketCreate(false);
SocketCleanable.register(fd);
SocketCleanable.register(fd, false);
} catch (IOException ioe) {
ResourceManager.afterUdpClose();
fd = null;
@ -136,7 +136,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
} else {
fd = new FileDescriptor();
socketCreate(true);
SocketCleanable.register(fd);
SocketCleanable.register(fd, true);
}
}
@ -580,7 +580,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
} finally {
releaseFD();
}
SocketCleanable.register(si.fd);
SocketCleanable.register(si.fd, true);
}
/**
@ -683,9 +683,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null) {
if (!stream) {
ResourceManager.afterUdpClose();
}
if (fdUseCount == 0) {
if (closePending) {
return;
@ -840,7 +837,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
*/
protected void socketClose() throws IOException {
SocketCleanable.unregister(fd);
socketClose0(false);
try {
socketClose0(false);
} finally {
if (!stream) {
ResourceManager.afterUdpClose();
}
}
}
abstract void socketCreate(boolean stream) throws IOException;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, 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
@ -34,6 +34,7 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.ref.Cleaner;
import sun.net.ResourceManager;
/**
* Cleanable for a socket/datagramsocket FileDescriptor when it becomes phantom reachable.
@ -56,17 +57,22 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
// The raw fd to close
private final int fd;
// true for socket, false for datagram socket
private final boolean stream;
/**
* Register a socket specific Cleanable with the FileDescriptor
* if the FileDescriptor is non-null and the raw fd is != -1.
*
* @param fdo the FileDescriptor; may be null
* @param fdo the FileDescriptor; may be null
* @param stream false for datagram socket
*/
static void register(FileDescriptor fdo) {
static void register(FileDescriptor fdo, boolean stream) {
if (fdo != null && fdo.valid()) {
int fd = fdAccess.get(fdo);
fdAccess.registerCleanup(fdo,
new SocketCleanable(fdo, CleanerFactory.cleaner(), fd));
new SocketCleanable(fdo, CleanerFactory.cleaner(),
fd, stream));
}
}
@ -86,10 +92,13 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
* @param obj the object to monitor
* @param cleaner the cleaner
* @param fd file descriptor to close
* @param stream false for datagram socket
*/
private SocketCleanable(FileDescriptor obj, Cleaner cleaner, int fd) {
private SocketCleanable(FileDescriptor obj, Cleaner cleaner,
int fd, boolean stream) {
super(obj, cleaner);
this.fd = fd;
this.stream = stream;
}
/**
@ -101,6 +110,10 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
cleanupClose0(fd);
} catch (IOException ioe) {
throw new UncheckedIOException("close", ioe);
} finally {
if (!stream) {
ResourceManager.afterUdpClose();
}
}
}
}

View file

@ -45,6 +45,7 @@ import java.util.ServiceLoader;
import jdk.internal.access.JavaNetURLAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
import sun.net.util.IPAddressUtil;
import sun.security.util.SecurityConstants;
import sun.security.action.GetPropertyAction;
@ -1431,7 +1432,7 @@ public final class URL implements java.io.Serializable {
boolean checkedWithFactory = false;
boolean overrideableProtocol = isOverrideable(protocol);
if (overrideableProtocol && jdk.internal.misc.VM.isBooted()) {
if (overrideableProtocol && VM.isBooted()) {
// Use the factory (if any). Volatile read makes
// URLStreamHandlerFactory appear fully initialized to current thread.
fac = factory;
@ -1665,7 +1666,9 @@ public final class URL implements java.io.Serializable {
}
boolean isBuiltinStreamHandler(URLStreamHandler handler) {
return isBuiltinStreamHandler(handler.getClass().getName());
Class<?> handlerClass = handler.getClass();
return isBuiltinStreamHandler(handlerClass.getName())
|| VM.isSystemDomainLoader(handlerClass.getClassLoader());
}
private boolean isBuiltinStreamHandler(String handlerClassName) {

View file

@ -3348,6 +3348,8 @@ public final class Files {
Objects.requireNonNull(cs);
byte[] ba = readAllBytes(path);
if (path.getClass().getModule() != Object.class.getModule())
ba = ba.clone();
return JLA.newStringNoRepl(ba, cs);
}

View file

@ -598,7 +598,7 @@ public class CodeSource implements java.io.Serializable {
cfs.put(certType, cf);
}
// parse the certificate
byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
byte[] encoded = IOUtils.readExactlyNBytes(ois, ois.readInt());
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
try {
certList.add(cf.generateCertificate(bais));

View file

@ -594,7 +594,7 @@ implements java.io.Serializable
cfs.put(certType, cf);
}
// parse the certificate
byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
byte[] encoded = IOUtils.readExactlyNBytes(ois, ois.readInt());
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
try {
certList.add(cf.generateCertificate(bais));

View file

@ -244,7 +244,7 @@ public class CertificateRevokedException extends CertificateException {
for (int i = 0; i < size; i++) {
String oid = (String) ois.readObject();
boolean critical = ois.readBoolean();
byte[] extVal = IOUtils.readNBytes(ois, ois.readInt());
byte[] extVal = IOUtils.readExactlyNBytes(ois, ois.readInt());
Extension ext = sun.security.x509.Extension.newExtension
(new ObjectIdentifier(oid), critical, extVal);
extensions.put(oid, ext);