This commit is contained in:
robm 2022-10-18 21:35:07 +01:00
commit bc946a4450
37 changed files with 982 additions and 328 deletions

View File

@ -45,6 +45,7 @@ endif
LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher
LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \
-I$(TOPDIR)/src/java.desktop/share/native/include \
-I$(TOPDIR)/src/java.base/share/native/libjli \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \

View File

@ -368,6 +368,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
common/awt/debug \
common/font \
common/java2d/opengl \
include \
#
LIBAWT_HEADLESS_CFLAGS := $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) $(X_CFLAGS) \
@ -477,6 +478,7 @@ LIBFONTMANAGER_EXTRA_HEADER_DIRS := \
libawt/java2d \
libawt/java2d/pipe \
libawt/java2d/loops \
include \
#
LIBFONTMANAGER_CFLAGS += $(LIBFREETYPE_CFLAGS)
@ -656,6 +658,8 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
common/awt/systemscale \
#
LIBSPLASHSCREEN_HEADER_DIRS += include
ifeq ($(USE_EXTERNAL_LIBGIF), false)
LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/giflib
else

View File

@ -657,6 +657,11 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
const size_t outer_size = size + MemTracker::overhead_per_malloc();
// Check for overflow.
if (outer_size < size) {
return NULL;
}
void* const outer_ptr = ::malloc(outer_size);
if (outer_ptr == NULL) {
return NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
@ -117,9 +117,10 @@ public final class Client extends NTLM {
* {@code nonce} is null for NTLM v1.
*/
public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
if (type2 == null || (v != Version.NTLM && nonce == null)) {
if (type2 == null || (v != Version.NTLM && nonce == null) ||
(nonce != null && nonce.length != 8)) {
throw new NTLMException(NTLMException.PROTOCOL,
"type2 and nonce cannot be null");
"type2 cannot be null, and nonce must be 8-byte long");
}
debug("NTLM Client: Type 2 received\n");
debug(type2);

View File

@ -224,23 +224,27 @@ class NTLM {
System.arraycopy(data, 0, internal, offset, data.length);
}
void writeSecurityBuffer(int offset, byte[] data) {
void writeSecurityBuffer(int offset, byte[] data) throws NTLMException {
if (data == null) {
writeShort(offset+4, current);
writeInt(offset+4, current);
} else {
int len = data.length;
if (len > 65535) {
throw new NTLMException(NTLMException.INVALID_INPUT,
"Invalid data length " + len);
}
if (current + len > internal.length) {
internal = Arrays.copyOf(internal, current + len + 256);
}
writeShort(offset, len);
writeShort(offset+2, len);
writeShort(offset+4, current);
writeInt(offset+4, current);
System.arraycopy(data, 0, internal, current, len);
current += len;
}
}
void writeSecurityBuffer(int offset, String str, boolean unicode) {
void writeSecurityBuffer(int offset, String str, boolean unicode) throws NTLMException {
writeSecurityBuffer(offset, str == null ? null : str.getBytes(
unicode ? StandardCharsets.UTF_16LE
: StandardCharsets.ISO_8859_1));

View File

@ -65,6 +65,11 @@ public final class NTLMException extends GeneralSecurityException {
*/
public static final int PROTOCOL = 6;
/**
* If an invalid input is provided.
*/
public static final int INVALID_INPUT = 7;
private int errorCode;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, 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
@ -85,9 +85,9 @@ public abstract class Server extends NTLM {
* {@code nonce} is null.
*/
public byte[] type2(byte[] type1, byte[] nonce) throws NTLMException {
if (nonce == null) {
if (nonce == null || nonce.length != 8) {
throw new NTLMException(NTLMException.PROTOCOL,
"nonce cannot be null");
"nonce must be 8-byte long");
}
debug("NTLM Server: Type 1 received\n");
if (type1 != null) debug(type1);

View File

@ -31,6 +31,10 @@ package java.math;
import static java.math.BigInteger.LONG_MASK;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.StreamCorruptedException;
import java.util.Arrays;
import java.util.Objects;
@ -1047,6 +1051,15 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
this.precision = prec;
}
/**
* Accept no subclasses.
*/
private static BigInteger toStrictBigInteger(BigInteger val) {
return (val.getClass() == BigInteger.class) ?
val :
new BigInteger(val.toByteArray().clone());
}
/**
* Translates a {@code BigInteger} into a {@code BigDecimal}.
* The scale of the {@code BigDecimal} is zero.
@ -1056,8 +1069,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
public BigDecimal(BigInteger val) {
scale = 0;
intVal = val;
intCompact = compactValFor(val);
intVal = toStrictBigInteger(val);
intCompact = compactValFor(intVal);
}
/**
@ -1071,7 +1084,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
*/
public BigDecimal(BigInteger val, MathContext mc) {
this(val,0,mc);
this(toStrictBigInteger(val), 0, mc);
}
/**
@ -1085,8 +1098,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
public BigDecimal(BigInteger unscaledVal, int scale) {
// Negative scales are now allowed
this.intVal = unscaledVal;
this.intCompact = compactValFor(unscaledVal);
this.intVal = toStrictBigInteger(unscaledVal);
this.intCompact = compactValFor(this.intVal);
this.scale = scale;
}
@ -1104,6 +1117,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
*/
public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
unscaledVal = toStrictBigInteger(unscaledVal);
long compactVal = compactValFor(unscaledVal);
int mcp = mc.precision;
int prec = 0;
@ -4246,9 +4260,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
= unsafe.objectFieldOffset(BigDecimal.class, "intCompact");
private static final long intValOffset
= unsafe.objectFieldOffset(BigDecimal.class, "intVal");
private static final long scaleOffset
= unsafe.objectFieldOffset(BigDecimal.class, "scale");
static void setIntCompact(BigDecimal bd, long val) {
unsafe.putLong(bd, intCompactOffset, val);
static void setIntValAndScale(BigDecimal bd, BigInteger intVal, int scale) {
unsafe.putReference(bd, intValOffset, intVal);
unsafe.putInt(bd, scaleOffset, scale);
unsafe.putLong(bd, intCompactOffset, compactValFor(intVal));
}
static void setIntValVolatile(BigDecimal bd, BigInteger val) {
@ -4267,15 +4285,30 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read in all fields
s.defaultReadObject();
// validate possibly bad fields
if (intVal == null) {
String message = "BigDecimal: null intVal in stream";
throw new java.io.StreamCorruptedException(message);
// [all values of scale are now allowed]
// prepare to read the fields
ObjectInputStream.GetField fields = s.readFields();
BigInteger serialIntVal = (BigInteger) fields.get("intVal", null);
// Validate field data
if (serialIntVal == null) {
throw new StreamCorruptedException("Null or missing intVal in BigDecimal stream");
}
UnsafeHolder.setIntCompact(this, compactValFor(intVal));
// Validate provenance of serialIntVal object
serialIntVal = toStrictBigInteger(serialIntVal);
// Any integer value is valid for scale
int serialScale = fields.get("scale", 0);
UnsafeHolder.setIntValAndScale(this, serialIntVal, serialScale);
}
/**
* Serialization without data not supported for this class.
*/
@java.io.Serial
private void readObjectNoData()
throws ObjectStreamException {
throw new InvalidObjectException("Deserialized BigDecimal objects need data");
}
/**

View File

@ -30,9 +30,11 @@
package java.math;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.ObjectStreamException;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
@ -4824,17 +4826,21 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// prepare to read the alternate persistent fields
ObjectInputStream.GetField fields = s.readFields();
// Read the alternate persistent fields that we care about
int sign = fields.get("signum", -2);
byte[] magnitude = (byte[])fields.get("magnitude", null);
// Read and validate the alternate persistent fields that we
// care about, signum and magnitude
// Validate signum
// Read and validate signum
int sign = fields.get("signum", -2);
if (sign < -1 || sign > 1) {
String message = "BigInteger: Invalid signum value";
if (fields.defaulted("signum"))
message = "BigInteger: Signum not present in stream";
throw new java.io.StreamCorruptedException(message);
}
// Read and validate magnitude
byte[] magnitude = (byte[])fields.get("magnitude", null);
magnitude = magnitude.clone(); // defensive copy
int[] mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
if ((mag.length == 0) != (sign == 0)) {
String message = "BigInteger: signum-magnitude mismatch";
@ -4843,18 +4849,24 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
throw new java.io.StreamCorruptedException(message);
}
// Commit final fields via Unsafe
UnsafeHolder.putSign(this, sign);
// Calculate mag field from magnitude and discard magnitude
UnsafeHolder.putMag(this, mag);
if (mag.length >= MAX_MAG_LENGTH) {
try {
checkRange();
} catch (ArithmeticException e) {
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
}
// Equivalent to checkRange() on mag local without assigning
// this.mag field
if (mag.length > MAX_MAG_LENGTH ||
(mag.length == MAX_MAG_LENGTH && mag[0] < 0)) {
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
}
// Commit final fields via Unsafe
UnsafeHolder.putSignAndMag(this, sign, mag);
}
/**
* Serialization without data not supported for this class.
*/
@java.io.Serial
private void readObjectNoData()
throws ObjectStreamException {
throw new InvalidObjectException("Deserialized BigInteger objects need data");
}
// Support for resetting final fields while deserializing
@ -4866,11 +4878,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
private static final long magOffset
= unsafe.objectFieldOffset(BigInteger.class, "mag");
static void putSign(BigInteger bi, int sign) {
static void putSignAndMag(BigInteger bi, int sign, int[] magnitude) {
unsafe.putInt(bi, signumOffset, sign);
}
static void putMag(BigInteger bi, int[] magnitude) {
unsafe.putReference(bi, magOffset, magnitude);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, 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
@ -153,7 +153,7 @@ implements java.io.Serializable
* Each chain is ordered bottom-to-top (i.e., with the signer certificate
* first and the (root) certificate authority last). The signer
* certificates are copied from the array. Subsequent changes to
* the array will not affect this UnsolvedPermission.
* the array will not affect this UnresolvedPermission.
*/
public UnresolvedPermission(String type,
String name,
@ -165,59 +165,63 @@ implements java.io.Serializable
if (type == null)
throw new NullPointerException("type can't be null");
// Perform a defensive copy and reassign certs if we have a non-null
// reference
if (certs != null) {
certs = certs.clone();
}
this.type = type;
this.name = name;
this.actions = actions;
if (certs != null) {
// Extract the signer certs from the list of certificates.
for (int i=0; i<certs.length; i++) {
for (int i = 0; i < certs.length; i++) {
if (!(certs[i] instanceof X509Certificate)) {
// there is no concept of signer certs, so we store the
// entire cert array
this.certs = certs.clone();
break;
// entire cert array. No further processing is necessary.
this.certs = certs;
return;
}
}
if (this.certs == null) {
// Go through the list of certs and see if all the certs are
// signer certs.
int i = 0;
int count = 0;
while (i < certs.length) {
count++;
while (((i+1) < certs.length) &&
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
((X509Certificate)certs[i+1]).getSubjectX500Principal())) {
i++;
}
// Go through the list of certs and see if all the certs are
// signer certs.
int i = 0;
int count = 0;
while (i < certs.length) {
count++;
while (((i + 1) < certs.length) &&
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
((X509Certificate)certs[i + 1]).getSubjectX500Principal())) {
i++;
}
if (count == certs.length) {
// All the certs are signer certs, so we store the entire
// array
this.certs = certs.clone();
}
if (this.certs == null) {
// extract the signer certs
ArrayList<java.security.cert.Certificate> signerCerts =
new ArrayList<>();
i = 0;
while (i < certs.length) {
signerCerts.add(certs[i]);
while (((i+1) < certs.length) &&
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
((X509Certificate)certs[i+1]).getSubjectX500Principal())) {
i++;
}
i++;
}
this.certs =
new java.security.cert.Certificate[signerCerts.size()];
signerCerts.toArray(this.certs);
}
i++;
}
if (count == certs.length) {
// All the certs are signer certs, so we store the entire
// array. No further processing is needed.
this.certs = certs;
return;
}
// extract the signer certs
ArrayList<java.security.cert.Certificate> signerCerts =
new ArrayList<>();
i = 0;
while (i < certs.length) {
signerCerts.add(certs[i]);
while (((i + 1) < certs.length) &&
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
((X509Certificate)certs[i + 1]).getSubjectX500Principal())) {
i++;
}
i++;
}
this.certs =
new java.security.cert.Certificate[signerCerts.size()];
signerCerts.toArray(this.certs);
}
}
@ -310,6 +314,7 @@ implements java.io.Serializable
*
* @return false.
*/
@Override
public boolean implies(Permission p) {
return false;
}
@ -330,6 +335,7 @@ implements java.io.Serializable
* type (class) name, permission name, actions, and
* certificates as this object.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@ -402,7 +408,7 @@ implements java.io.Serializable
*
* @return a hash code value for this object.
*/
@Override
public int hashCode() {
int hash = type.hashCode();
if (name != null)
@ -422,6 +428,7 @@ implements java.io.Serializable
*
* @return the empty string "".
*/
@Override
public String getActions()
{
return "";
@ -489,6 +496,7 @@ implements java.io.Serializable
*
* @return information about this UnresolvedPermission.
*/
@Override
public String toString() {
return "(unresolved " + type + " " + name + " " + actions + ")";
}
@ -500,7 +508,7 @@ implements java.io.Serializable
* @return a new PermissionCollection object suitable for
* storing UnresolvedPermissions.
*/
@Override
public PermissionCollection newPermissionCollection() {
return new UnresolvedPermissionCollection();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2022, 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
@ -347,5 +347,40 @@ public final class ECUtil {
return prv;
}
// Partial Public key validation as described in NIST SP 800-186 Appendix D.1.1.1.
// The extra step in the full validation (described in Appendix D.1.1.2) is implemented
// as sun.security.ec.ECOperations#checkOrder inside the jdk.crypto.ec module.
public static void validatePublicKey(ECPoint point, ECParameterSpec spec)
throws InvalidKeyException {
BigInteger p;
if (spec.getCurve().getField() instanceof ECFieldFp f) {
p = f.getP();
} else {
throw new InvalidKeyException("Only curves over prime fields are supported");
}
// 1. If Q is the point at infinity, output REJECT
if (point.equals(ECPoint.POINT_INFINITY)) {
throw new InvalidKeyException("Public point is at infinity");
}
// 2. Verify that x and y are integers in the interval [0, p-1]. Output REJECT if verification fails.
BigInteger x = point.getAffineX();
if (x.signum() < 0 || x.compareTo(p) >= 0) {
throw new InvalidKeyException("Public point x is not in the interval [0, p-1]");
}
BigInteger y = point.getAffineY();
if (y.signum() < 0 || y.compareTo(p) >= 0) {
throw new InvalidKeyException("Public point y is not in the interval [0, p-1]");
}
// 3. Verify that (x, y) is a point on the W_a,b by checking that (x, y) satisfies the defining
// equation y^2 = x^3 + a x + b where computations are carried out in GF(p). Output REJECT
// if verification fails.
BigInteger left = y.modPow(BigInteger.TWO, p);
BigInteger right = x.pow(3).add(spec.getCurve().getA().multiply(x)).add(spec.getCurve().getB()).mod(p);
if (!left.equals(right)) {
throw new InvalidKeyException("Public point is not on the curve");
}
}
private ECUtil() {}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2022, 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
@ -46,8 +46,13 @@
#define IS_SAFE_SIZE_T(x) ((x) >= 0 && (unsigned long long)(x) <= SIZE_MAX)
#define IS_MUL_OVERFLOW(m, n) \
((m) != 0 && (n) != 0 && (((size_t)((m)*(n))) != (((size_t)(m)) * ((size_t)(n)))))
#define IS_SAFE_SIZE_MUL(m, n) \
(IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && ((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m))))
(IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && \
((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m))) && \
!IS_MUL_OVERFLOW(m, n))
#define IS_SAFE_SIZE_ADD(a, b) \
(IS_SAFE_SIZE_T(a) && IS_SAFE_SIZE_T(b) && (size_t)(b) <= (SIZE_MAX - (size_t)(a)))

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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
@ -1043,7 +1043,7 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits
// limit iconSize to MAX_ICON_SIZE, so that the colorBits and maskBits
// arrays are big enough.
// (logic: rather show bad icons than overrun the array size)
iconSize = iconSize > MAX_ICON_SIZE ? MAX_ICON_SIZE : iconSize;
iconSize = (iconSize <= 0 || iconSize > MAX_ICON_SIZE) ? MAX_ICON_SIZE : iconSize;
// Set up BITMAPINFO
BITMAPINFO bmi;

View File

@ -103,7 +103,7 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection {
@Override
ConnectionPool.CacheKey cacheKey() {
return ConnectionPool.cacheKey(address, null);
return ConnectionPool.cacheKey(true, address, null);
}
@Override

View File

@ -28,7 +28,6 @@ package jdk.internal.net.http;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CompletableFuture;
import java.net.http.HttpHeaders;
import java.util.function.Function;
import jdk.internal.net.http.common.MinimalFuture;
import jdk.internal.net.http.common.SSLTube;
@ -106,7 +105,7 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
@Override
ConnectionPool.CacheKey cacheKey() {
return ConnectionPool.cacheKey(address, plainConnection.proxyAddr);
return ConnectionPool.cacheKey(true, address, plainConnection.proxyAddr);
}
@Override

View File

@ -26,7 +26,6 @@
package jdk.internal.net.http;
import java.io.IOException;
import java.lang.System.Logger.Level;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.time.Instant;
@ -68,18 +67,21 @@ final class ConnectionPool {
/**
* Entries in connection pool are keyed by destination address and/or
* proxy address:
* case 1: plain TCP not via proxy (destination only)
* case 1: plain TCP not via proxy (destination IP only)
* case 2: plain TCP via proxy (proxy only)
* case 3: SSL not via proxy (destination only)
* case 4: SSL over tunnel (destination and proxy)
* case 3: SSL not via proxy (destination IP+hostname only)
* case 4: SSL over tunnel (destination IP+hostname and proxy)
*/
static class CacheKey {
final InetSocketAddress proxy;
final InetSocketAddress destination;
final boolean secure;
CacheKey(InetSocketAddress destination, InetSocketAddress proxy) {
private CacheKey(boolean secure, InetSocketAddress destination,
InetSocketAddress proxy) {
this.proxy = proxy;
this.destination = destination;
this.secure = secure;
}
@Override
@ -91,12 +93,26 @@ final class ConnectionPool {
return false;
}
final CacheKey other = (CacheKey) obj;
if (this.secure != other.secure) {
return false;
}
if (!Objects.equals(this.proxy, other.proxy)) {
return false;
}
if (!Objects.equals(this.destination, other.destination)) {
return false;
}
if (secure && destination != null) {
if (destination.getHostName() != null) {
if (!destination.getHostName().equalsIgnoreCase(
other.destination.getHostName())) {
return false;
}
} else {
if (other.destination.getHostName() != null)
return false;
}
}
return true;
}
@ -128,10 +144,10 @@ final class ConnectionPool {
assert !stopped : "Already stopped";
}
static CacheKey cacheKey(InetSocketAddress destination,
static CacheKey cacheKey(boolean secure, InetSocketAddress destination,
InetSocketAddress proxy)
{
return new CacheKey(destination, proxy);
return new CacheKey(secure, destination, proxy);
}
synchronized HttpConnection getConnection(boolean secure,
@ -140,7 +156,7 @@ final class ConnectionPool {
if (stopped) return null;
// for plain (unsecure) proxy connection the destination address is irrelevant.
addr = secure || proxy == null ? addr : null;
CacheKey key = new CacheKey(addr, proxy);
CacheKey key = new CacheKey(secure, addr, proxy);
HttpConnection c = secure ? findConnection(key, sslPool)
: findConnection(key, plainPool);
//System.out.println ("getConnection returning: " + c);

View File

@ -414,7 +414,7 @@ class PlainHttpConnection extends HttpConnection {
@Override
ConnectionPool.CacheKey cacheKey() {
return new ConnectionPool.CacheKey(address, null);
return ConnectionPool.cacheKey(false, address, null);
}
@Override

View File

@ -35,7 +35,7 @@ class PlainProxyConnection extends PlainHttpConnection {
@Override
ConnectionPool.CacheKey cacheKey() {
return new ConnectionPool.CacheKey(null, address);
return ConnectionPool.cacheKey(false, null, address);
}
@Override

View File

@ -30,11 +30,10 @@ import java.net.InetSocketAddress;
import java.net.http.HttpTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.function.Function;
import java.net.http.HttpHeaders;
import jdk.internal.net.http.common.FlowTube;
import jdk.internal.net.http.common.MinimalFuture;
import static java.net.http.HttpResponse.BodyHandlers.discarding;
@ -153,7 +152,7 @@ final class PlainTunnelingConnection extends HttpConnection {
@Override
ConnectionPool.CacheKey cacheKey() {
return new ConnectionPool.CacheKey(null, proxyAddr);
return ConnectionPool.cacheKey(false, null, proxyAddr);
}
@Override

View File

@ -897,7 +897,7 @@ gss_init_sec_context(OM_uint32 *minor_status,
gss_buffer_desc tn;
gss_display_name(&minor, target_name, &tn, NULL);
int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)tn.value, (int)tn.length,
outName, sizeof(outName) - 1);
outName, (sizeof(outName) / sizeof(outName[0])) - 1);
if (len == 0) {
goto err;
}

View File

@ -463,8 +463,7 @@ abstract class ECDSASignature extends SignatureSpi {
Optional<ECDSAOperations> opsOpt =
ECDSAOperations.forParameters(params);
if (opsOpt.isEmpty()) {
throw new SignatureException("Curve not supported: " +
params.toString());
throw new SignatureException("Curve not supported: " + params);
}
byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest, privateKey,
random);
@ -480,22 +479,33 @@ abstract class ECDSASignature extends SignatureSpi {
@Override
protected boolean engineVerify(byte[] signature) throws SignatureException {
ECPoint w = publicKey.getW();
ECParameterSpec params = publicKey.getParams();
// Partial public key validation
try {
ECUtil.validatePublicKey(w, params);
} catch (InvalidKeyException e) {
return false;
}
ECDSAOperations ops = ECDSAOperations.forParameters(params)
.orElseThrow(() -> new SignatureException("Curve not supported: " + params));
// Full public key validation, only necessary when h != 1.
if (params.getCofactor() != 1) {
if (!ops.getEcOperations().checkOrder(w)) {
return false;
}
}
byte[] sig;
if (p1363Format) {
sig = signature;
} else {
sig = ECUtil.decodeSignature(signature);
}
byte[] digest = getDigestValue();
Optional<ECDSAOperations> opsOpt =
ECDSAOperations.forParameters(publicKey.getParams());
if (opsOpt.isEmpty()) {
throw new SignatureException("Curve not supported: " +
publicKey.getParams().toString());
}
return opsOpt.get().verifySignedDigest(digest, sig, publicKey.getW());
return ops.verifySignedDigest(getDigestValue(), sig, w);
}
// set parameter, not supported. See JCA doc

View File

@ -26,6 +26,7 @@
package sun.security.ec;
import sun.security.ec.point.*;
import sun.security.util.ArrayUtil;
import sun.security.util.math.*;
import sun.security.util.math.intpoly.*;
@ -33,6 +34,7 @@ import java.math.BigInteger;
import java.security.ProviderException;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.Map;
import java.util.Optional;
@ -489,5 +491,19 @@ public class ECOperations {
p.getZ().setSum(t1);
}
// The extra step in the Full Public key validation as described in
// NIST SP 800-186 Appendix D.1.1.2
public boolean checkOrder(ECPoint point) {
BigInteger x = point.getAffineX();
BigInteger y = point.getAffineY();
// Verify that n Q = INFINITY. Output REJECT if verification fails.
IntegerFieldModuloP field = this.getField();
AffinePoint ap = new AffinePoint(field.getElement(x), field.getElement(y));
byte[] scalar = this.orderField.getSize().toByteArray();
ArrayUtil.reverse(scalar);
return isNeutral(this.multiply(ap, scalar));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, 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
@ -30,8 +30,6 @@ import javax.net.ssl.*;
import java.nio.channels.*;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.spi.*;
/**
* encapsulates all the connection specific state for a HTTP/S connection
@ -55,14 +53,14 @@ class HttpConnection {
SocketChannel chan;
SelectionKey selectionKey;
String protocol;
long time;
volatile long creationTime; // time this connection was created
long idleStartTime; // absolute time in milli seconds, starting when the connection was marked idle
volatile long reqStartedTime; // time when the request was initiated
volatile long rspStartedTime; // time we started writing the response
int remaining;
boolean closed = false;
Logger logger;
public enum State {IDLE, REQUEST, RESPONSE};
public enum State {IDLE, REQUEST, RESPONSE, NEWLY_ACCEPTED};
volatile State state;
public String toString() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, 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
@ -44,7 +44,6 @@ class SSLStreams {
SSLContext sslctx;
SocketChannel chan;
TimeSource time;
ServerImpl server;
SSLEngine engine;
EngineWrapper wrapper;
@ -56,7 +55,6 @@ class SSLStreams {
SSLStreams (ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException {
this.server = server;
this.time= (TimeSource)server;
this.sslctx= sslctx;
this.chan= chan;
InetSocketAddress addr =

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, 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
@ -37,29 +37,35 @@ import java.security.PrivilegedAction;
@SuppressWarnings("removal")
class ServerConfig {
private static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec.
private static final int DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS = 10000 ; // 10 sec.
/* These values must be a reasonable multiple of clockTick */
private static final long DEFAULT_IDLE_INTERVAL = 30 ; // 5 min
private static final long DEFAULT_IDLE_INTERVAL_IN_SECS = 30;
private static final int DEFAULT_MAX_CONNECTIONS = -1 ; // no limit on maximum connections
private static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ;
private static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever
private static final long DEFAULT_MAX_RSP_TIME = -1; // default: forever
private static final long DEFAULT_TIMER_MILLIS = 1000;
// default timer schedule, in milli seconds, for the timer task that's responsible for
// timing out request/response if max request/response time is configured
private static final long DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS = 1000;
private static final int DEFAULT_MAX_REQ_HEADERS = 200;
private static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024;
private static int clockTick;
private static long idleInterval;
private static long idleTimerScheduleMillis;
private static long idleIntervalMillis;
// The maximum number of bytes to drain from an inputstream
private static long drainAmount;
// the maximum number of connections that the server will allow to be open
// after which it will no longer "accept()" any new connections, till the
// current connection count goes down due to completion of processing the requests
private static int maxConnections;
private static int maxIdleConnections;
// The maximum number of request headers allowable
private static int maxReqHeaders;
// max time a request or response is allowed to take
private static long maxReqTime;
private static long maxRspTime;
private static long timerMillis;
private static long reqRspTimerScheduleMillis;
private static boolean debug;
// the value of the TCP_NODELAY socket-level option
@ -70,11 +76,22 @@ class ServerConfig {
new PrivilegedAction<Void>() {
@Override
public Void run () {
idleInterval = Long.getLong("sun.net.httpserver.idleInterval",
DEFAULT_IDLE_INTERVAL) * 1000;
idleIntervalMillis = Long.getLong("sun.net.httpserver.idleInterval",
DEFAULT_IDLE_INTERVAL_IN_SECS) * 1000;
if (idleIntervalMillis <= 0) {
idleIntervalMillis = DEFAULT_IDLE_INTERVAL_IN_SECS * 1000;
}
clockTick = Integer.getInteger("sun.net.httpserver.clockTick",
DEFAULT_CLOCK_TICK);
idleTimerScheduleMillis = Long.getLong("sun.net.httpserver.clockTick",
DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS);
if (idleTimerScheduleMillis <= 0) {
// ignore zero or negative value and use the default schedule
idleTimerScheduleMillis = DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS;
}
maxConnections = Integer.getInteger(
"jdk.httpserver.maxConnections",
DEFAULT_MAX_CONNECTIONS);
maxIdleConnections = Integer.getInteger(
"sun.net.httpserver.maxIdleConnections",
@ -93,8 +110,13 @@ class ServerConfig {
maxRspTime = Long.getLong("sun.net.httpserver.maxRspTime",
DEFAULT_MAX_RSP_TIME);
timerMillis = Long.getLong("sun.net.httpserver.timerMillis",
DEFAULT_TIMER_MILLIS);
reqRspTimerScheduleMillis = Long.getLong("sun.net.httpserver.timerMillis",
DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS);
if (reqRspTimerScheduleMillis <= 0) {
// ignore any negative or zero value for this configuration and reset
// to default schedule
reqRspTimerScheduleMillis = DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS;
}
debug = Boolean.getBoolean("sun.net.httpserver.debug");
@ -150,14 +172,34 @@ class ServerConfig {
return debug;
}
static long getIdleInterval() {
return idleInterval;
/**
* {@return Returns the maximum duration, in milli seconds, a connection can be idle}
*/
static long getIdleIntervalMillis() {
return idleIntervalMillis;
}
static int getClockTick() {
return clockTick;
/**
* {@return Returns the schedule, in milli seconds, for the timer task that is responsible
* for managing the idle connections}
*/
static long getIdleTimerScheduleMillis() {
return idleTimerScheduleMillis;
}
/**
* @return Returns the maximum number of connections that can be open at any given time.
* This method can return a value of 0 or negative to represent that the limit hasn't
* been configured.
*/
static int getMaxConnections() {
return maxConnections;
}
/**
* @return Returns the maximum number of connections that can be idle. This method
* can return a value of 0 or negative.
*/
static int getMaxIdleConnections() {
return maxIdleConnections;
}
@ -170,16 +212,30 @@ class ServerConfig {
return maxReqHeaders;
}
/**
* @return Returns the maximum amount of time the server will wait for the request to be read
* completely. This method can return a value of 0 or negative to imply no maximum limit has
* been configured.
*/
static long getMaxReqTime() {
return maxReqTime;
}
/**
* @return Returns the maximum amount of time the server will wait for the response to be generated
* for a request that is being processed. This method can return a value of 0 or negative to
* imply no maximum limit has been configured.
*/
static long getMaxRspTime() {
return maxRspTime;
}
static long getTimerMillis() {
return timerMillis;
/**
* {@return Returns the timer schedule of the task that's responsible for timing out
* request/response that have been running longer than any configured timeout}
*/
static long getReqRspTimerScheduleMillis() {
return reqRspTimerScheduleMillis;
}
static boolean noDelay() {

View File

@ -25,26 +25,52 @@
package sun.net.httpserver;
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import javax.net.ssl.*;
import com.sun.net.httpserver.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import sun.net.httpserver.HttpConnection.State;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static sun.net.httpserver.Utils.*;
import static sun.net.httpserver.Utils.isValidName;
/**
* Provides implementation for both HTTP and HTTPS
*/
class ServerImpl implements TimeSource {
class ServerImpl {
private String protocol;
private boolean https;
@ -56,32 +82,47 @@ class ServerImpl implements TimeSource {
private ServerSocketChannel schan;
private Selector selector;
private SelectionKey listenerKey;
private Set<HttpConnection> idleConnections;
private Set<HttpConnection> allConnections;
private final Set<HttpConnection> idleConnections;
// connections which have been accepted() by the server but which haven't
// yet sent any byte on the connection yet
private final Set<HttpConnection> newlyAcceptedConnections;
private final Set<HttpConnection> allConnections;
/* following two are used to keep track of the times
* when a connection/request is first received
* and when we start to send the response
*/
private Set<HttpConnection> reqConnections;
private Set<HttpConnection> rspConnections;
private final Set<HttpConnection> reqConnections;
private final Set<HttpConnection> rspConnections;
private List<Event> events;
private Object lolock = new Object();
private final Object lolock = new Object();
private volatile boolean finished = false;
private volatile boolean terminating = false;
private boolean bound = false;
private boolean started = false;
private volatile long time; /* current time */
private volatile long subticks = 0;
private volatile long ticks; /* number of clock ticks since server started */
private HttpServer wrapper;
static final int CLOCK_TICK = ServerConfig.getClockTick();
static final long IDLE_INTERVAL = ServerConfig.getIdleInterval();
// schedule for the timer task that's responsible for idle connection management
static final long IDLE_TIMER_TASK_SCHEDULE = ServerConfig.getIdleTimerScheduleMillis();
static final int MAX_CONNECTIONS = ServerConfig.getMaxConnections();
static final int MAX_IDLE_CONNECTIONS = ServerConfig.getMaxIdleConnections();
static final long TIMER_MILLIS = ServerConfig.getTimerMillis ();
static final long MAX_REQ_TIME=getTimeMillis(ServerConfig.getMaxReqTime());
static final long MAX_RSP_TIME=getTimeMillis(ServerConfig.getMaxRspTime());
static final boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
// schedule for the timer task that's responsible for request/response timeout management
static final long REQ_RSP_TIMER_SCHEDULE = ServerConfig.getReqRspTimerScheduleMillis();
static final long MAX_REQ_TIME = getTimeMillis(ServerConfig.getMaxReqTime());
static final long MAX_RSP_TIME = getTimeMillis(ServerConfig.getMaxRspTime());
static final boolean reqRspTimeoutEnabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
// the maximum idle duration for a connection which is currently idle but has served
// some request in the past
static final long IDLE_INTERVAL = ServerConfig.getIdleIntervalMillis();
// the maximum idle duration for a newly accepted connection which hasn't yet received
// the first byte of data on that connection
static final long NEWLY_ACCEPTED_CONN_IDLE_INTERVAL;
static {
// the idle duration of a newly accepted connection is considered to be the least of the
// configured idle interval and the configured max request time (if any).
NEWLY_ACCEPTED_CONN_IDLE_INTERVAL = MAX_REQ_TIME > 0
? Math.min(IDLE_INTERVAL, MAX_REQ_TIME)
: IDLE_INTERVAL;
}
private Timer timer, timer1;
private final Logger logger;
@ -112,13 +153,14 @@ class ServerImpl implements TimeSource {
allConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
reqConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
rspConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
time = System.currentTimeMillis();
timer = new Timer ("server-timer", true);
timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK);
if (timer1Enabled) {
timer1 = new Timer ("server-timer1", true);
timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS);
logger.log (Level.DEBUG, "HttpServer timer1 enabled period in ms: ", TIMER_MILLIS);
newlyAcceptedConnections = Collections.synchronizedSet(new HashSet<>());
timer = new Timer ("idle-timeout-task", true);
timer.schedule (new IdleTimeoutTask(), IDLE_TIMER_TASK_SCHEDULE, IDLE_TIMER_TASK_SCHEDULE);
if (reqRspTimeoutEnabled) {
timer1 = new Timer ("req-rsp-timeout-task", true);
timer1.schedule (new ReqRspTimeoutTask(), REQ_RSP_TIMER_SCHEDULE, REQ_RSP_TIMER_SCHEDULE);
logger.log(Level.DEBUG, "HttpServer request/response timeout task schedule ms: ",
REQ_RSP_TIMER_SCHEDULE);
logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME);
logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME);
}
@ -209,8 +251,9 @@ class ServerImpl implements TimeSource {
}
allConnections.clear();
idleConnections.clear();
newlyAcceptedConnections.clear();
timer.cancel();
if (timer1Enabled) {
if (reqRspTimeoutEnabled) {
timer1.cancel();
}
if (dispatcherThread != null && dispatcherThread != Thread.currentThread()) {
@ -273,10 +316,6 @@ class ServerImpl implements TimeSource {
});
}
Selector getSelector () {
return selector;
}
void addEvent (Event r) {
synchronized (lolock) {
events.add (r);
@ -286,6 +325,70 @@ class ServerImpl implements TimeSource {
/* main server listener task */
/**
* The Dispatcher is responsible for accepting any connections and then using those connections
* to processing any incoming requests. A connection is represented as an instance of
* sun.net.httpserver.HttpConnection.
*
* Connection states:
* An instance of HttpConnection goes through the following states:
*
* - NEWLY_ACCEPTED: A connection is marked as newly accepted as soon as the Dispatcher
* accept()s a connection. A newly accepted connection is added to a newlyAcceptedConnections
* collection. A newly accepted connection also gets added to the allConnections collection.
* The newlyAcceptedConnections isn't checked for any size limits, however, if the server is
* configured with a maximum connection limit, then the elements in the
* newlyAcceptedConnections will never exceed that configured limit (no explicit size checks
* are done on the newlyAcceptedConnections collection, since the maximum connection limit
* applies to connections across different connection states). A connection in NEWLY_ACCEPTED
* state is considered idle and is eligible for idle connection management.
*
* - REQUEST: A connection is marked to be in REQUEST state when the request processing starts
* on that connection. This typically happens when the first byte of data is received on a
* NEWLY_ACCEPTED connection or when new data arrives on a connection which was previously
* in IDLE state. When a connection is in REQUEST state, it implies that the connection is
* active and thus isn't eligible for idle connection management. If the server is configured
* with a maximum request timeout, then connections in REQUEST state are eligible
* for Request/Response timeout management.
*
* - RESPONSE: A connection is marked to be in RESPONSE state when the server has finished
* reading the request. A connection is RESPONSE state is considered active and isn't eligible
* for idle connection management. If the server is configured with a maximum response timeout,
* then connections in RESPONSE state are eligible for Request/Response timeout management.
*
* - IDLE: A connection is marked as IDLE when a request/response cycle (successfully) completes
* on that particular connection. Idle connections are held in a idleConnections collection.
* The idleConnections collection is limited in size and the size is decided by a server
* configuration. Connections in IDLE state get added to the idleConnections collection only
* if that collection hasn't reached the configured limit. If a connection has reached IDLE
* state and there's no more room in the idleConnections collection, then such a connection
* gets closed. Connections in idleConnections collection are eligible for idle connection
* management.
*
* Idle connection management:
* A timer task is responsible for closing idle connections. Each connection that is in a state
* which is eligible for idle timeout management (see above section on connection states)
* will have a corresponding idle expiration time associated with it. The idle timeout management
* task will check the expiration time of each such connection against the current time and will
* close the connection if the current time is either equal to or past the expiration time.
*
* Request/Response timeout management:
* The server can be optionally configured with a maximum request timeout and/or maximum response
* timeout. If either of these timeouts have been configured, then an additional timer task is
* run by the server. This timer task is then responsible for closing connections which have
* been in REQUEST or RESPONSE state for a period of time that exceeds the respective configured
* timeouts.
*
* Maximum connection limit management:
* The server can be optionally configured with a maximum connection limit. A value of 0 or
* negative integer is ignored and considered to represent no connection limit. In case of a
* positive integer value, any newly accepted connections will be first checked against the
* current count of established connections (held by the allConnections collection) and if the
* configured limit has reached, then the newly accepted connection will be closed immediately
* (even before setting its state to NEWLY_ACCEPTED or adding it to the newlyAcceptedConnections
* collection).
*
*/
class Dispatcher implements Runnable {
private void handleEvent (Event r) {
@ -339,8 +442,7 @@ class ServerImpl implements TimeSource {
SelectionKey key = chan.register (selector, SelectionKey.OP_READ);
key.attach (c);
c.selectionKey = key;
c.time = getTime() + IDLE_INTERVAL;
idleConnections.add (c);
markIdle(c);
} catch (IOException e) {
dprint(e);
logger.log (Level.TRACE, "Dispatcher(8)", e);
@ -387,9 +489,19 @@ class ServerImpl implements TimeSource {
continue;
}
SocketChannel chan = schan.accept();
// optimist there's a channel
if (chan != null) {
if (MAX_CONNECTIONS > 0 && allConnections.size() >= MAX_CONNECTIONS) {
// we've hit max limit of current open connections, so we go
// ahead and close this connection without processing it
try {
chan.close();
} catch (IOException ignore) {
}
// move on to next selected key
continue;
}
// Set TCP_NODELAY, if appropriate
if (ServerConfig.noDelay()) {
chan.socket().setTcpNoDelay(true);
@ -401,7 +513,7 @@ class ServerImpl implements TimeSource {
c.selectionKey = newkey;
c.setChannel (chan);
newkey.attach (c);
requestStarted (c);
markNewlyAccepted(c);
allConnections.add (c);
}
} else {
@ -412,10 +524,12 @@ class ServerImpl implements TimeSource {
key.cancel();
chan.configureBlocking (true);
if (idleConnections.remove(conn)) {
// was an idle connection so add it
// to reqConnections set.
requestStarted (conn);
if (newlyAcceptedConnections.remove(conn)
|| idleConnections.remove(conn)) {
// was either a newly accepted connection or an idle
// connection. In either case, we mark that the request
// has now started on this connection.
requestStarted(conn);
}
handle (chan, conn);
} else {
@ -497,10 +611,14 @@ class ServerImpl implements TimeSource {
case IDLE:
idleConnections.remove(conn);
break;
case NEWLY_ACCEPTED:
newlyAcceptedConnections.remove(conn);
break;
}
assert !reqConnections.remove(conn);
assert !rspConnections.remove(conn);
assert !idleConnections.remove(conn);
assert !newlyAcceptedConnections.remove(conn);
}
/* per exchange task */
@ -672,9 +790,9 @@ class ServerImpl implements TimeSource {
rheaders.set ("Connection", "close");
} else if (chdr.equalsIgnoreCase ("keep-alive")) {
rheaders.set ("Connection", "keep-alive");
int idle=(int)(ServerConfig.getIdleInterval()/1000);
int idleSeconds = (int) (ServerConfig.getIdleIntervalMillis() / 1000);
int max=ServerConfig.getMaxIdleConnections();
String val = "timeout="+idle+", max="+max;
String val = "timeout="+idleSeconds+", max="+max;
rheaders.set ("Keep-Alive", val);
}
}
@ -815,14 +933,6 @@ class ServerImpl implements TimeSource {
logger.log (Level.DEBUG, message);
}
long getTicks() {
return ticks;
}
public long getTime() {
return time;
}
void delay () {
Thread.yield();
try {
@ -847,11 +957,23 @@ class ServerImpl implements TimeSource {
}
void requestStarted (HttpConnection c) {
c.creationTime = getTime();
c.reqStartedTime = System.currentTimeMillis();
c.setState (State.REQUEST);
reqConnections.add (c);
}
void markIdle(HttpConnection c) {
c.idleStartTime = System.currentTimeMillis();
c.setState(State.IDLE);
idleConnections.add(c);
}
void markNewlyAccepted(HttpConnection c) {
c.idleStartTime = System.currentTimeMillis();
c.setState(State.NEWLY_ACCEPTED);
newlyAcceptedConnections.add(c);
}
// called after a request has been completely read
// by the server. This stops the timer which would
// close the connection if the request doesn't arrive
@ -863,7 +985,7 @@ class ServerImpl implements TimeSource {
State s = c.getState();
assert s == State.REQUEST : "State is not REQUEST ("+s+")";
reqConnections.remove (c);
c.rspStartedTime = getTime();
c.rspStartedTime = System.currentTimeMillis();
rspConnections.add (c);
c.setState (State.RESPONSE);
}
@ -877,38 +999,58 @@ class ServerImpl implements TimeSource {
}
/**
* Responsible for closing connections that have been idle.
* TimerTask run every CLOCK_TICK ms
*/
class ServerTimerTask extends TimerTask {
class IdleTimeoutTask extends TimerTask {
public void run () {
LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
time = System.currentTimeMillis();
ticks ++;
final long currentTime = System.currentTimeMillis();
synchronized (idleConnections) {
for (HttpConnection c : idleConnections) {
if (c.time <= time) {
toClose.add (c);
final Iterator<HttpConnection> it = idleConnections.iterator();
while (it.hasNext()) {
final HttpConnection c = it.next();
if (currentTime - c.idleStartTime >= IDLE_INTERVAL) {
toClose.add(c);
it.remove();
}
}
for (HttpConnection c : toClose) {
idleConnections.remove (c);
allConnections.remove (c);
c.close();
}
// if any newly accepted connection has been idle (i.e. no byte has been sent on that
// connection during the configured idle timeout period) then close it as well
synchronized (newlyAcceptedConnections) {
final Iterator<HttpConnection> it = newlyAcceptedConnections.iterator();
while (it.hasNext()) {
final HttpConnection c = it.next();
if (currentTime - c.idleStartTime >= NEWLY_ACCEPTED_CONN_IDLE_INTERVAL) {
toClose.add(c);
it.remove();
}
}
}
for (HttpConnection c : toClose) {
allConnections.remove(c);
c.close();
if (logger.isLoggable(Level.TRACE)) {
logger.log(Level.TRACE, "Closed idle connection " + c);
}
}
}
}
class ServerTimerTask1 extends TimerTask {
/**
* Responsible for closing connections which have timed out while in REQUEST or RESPONSE state
*/
class ReqRspTimeoutTask extends TimerTask {
// runs every TIMER_MILLIS
public void run () {
LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
time = System.currentTimeMillis();
final long currentTime = System.currentTimeMillis();
synchronized (reqConnections) {
if (MAX_REQ_TIME != -1) {
for (HttpConnection c : reqConnections) {
if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) {
if (currentTime - c.reqStartedTime >= MAX_REQ_TIME) {
toClose.add (c);
}
}
@ -924,7 +1066,7 @@ class ServerImpl implements TimeSource {
synchronized (rspConnections) {
if (MAX_RSP_TIME != -1) {
for (HttpConnection c : rspConnections) {
if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) {
if (currentTime - c.rspStartedTime >= MAX_RSP_TIME) {
toClose.add (c);
}
}
@ -939,21 +1081,17 @@ class ServerImpl implements TimeSource {
}
}
void logStackTrace (String s) {
logger.log (Level.TRACE, s);
StringBuilder b = new StringBuilder ();
StackTraceElement[] e = Thread.currentThread().getStackTrace();
for (int i=0; i<e.length; i++) {
b.append (e[i].toString()).append("\n");
}
logger.log (Level.TRACE, b.toString());
}
static long getTimeMillis(long secs) {
if (secs == -1) {
/**
* Converts and returns the passed {@code secs} as milli seconds. If the passed {@code secs}
* is negative or zero or if the conversion from seconds to milli seconds results in a negative
* number, then this method returns -1.
*/
private static long getTimeMillis(long secs) {
if (secs <= 0) {
return -1;
} else {
return secs * 1000;
}
final long milli = secs * 1000;
// this handles potential numeric overflow that may have happened during conversion
return milli > 0 ? milli : -1;
}
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (c) 2005, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.net.httpserver;
interface TimeSource {
public long getTime();
}

View File

@ -26,6 +26,9 @@
package sun.net.httpserver.simpleserver;
import java.io.PrintWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
@ -33,6 +36,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
*/
public class JWebServer {
private static final String SYS_PROP_MAX_CONNECTIONS = "jdk.httpserver.maxConnections";
private static final String DEFAULT_JWEBSERVER_MAX_CONNECTIONS = "200";
/**
* This constructor should never be called.
*/
@ -59,6 +65,7 @@ public class JWebServer {
*/
public static void main(String... args) {
setMaxReqTime();
setMaxConnectionsIfNotSet();
int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "jwebserver", args);
if (ec != 0) {
@ -76,4 +83,16 @@ public class JWebServer {
System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL);
}
}
@SuppressWarnings("removal")
static void setMaxConnectionsIfNotSet() {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
if (System.getProperty(SYS_PROP_MAX_CONNECTIONS) != null) {
// an explicit value has already been set, so we don't override it
return null;
}
System.setProperty(SYS_PROP_MAX_CONNECTIONS, DEFAULT_JWEBSERVER_MAX_CONNECTIONS);
return null;
});
}
}

View File

@ -59,6 +59,7 @@ public class Main {
*/
public static void main(String... args) {
setMaxReqTime();
JWebServer.setMaxConnectionsIfNotSet();
int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "java", args);
if (ec != 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, 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
@ -30,6 +30,8 @@ import java.net.ProtocolFamily;
import java.net.SocketException;
import java.net.InetSocketAddress;
import java.nio.channels.DatagramChannel;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import java.util.Random;
@ -50,6 +52,21 @@ class DNSDatagramSocketFactory {
static final int RANGE = UPPER - LOWER + 1;
}
private static int findFirstFreePort() {
PrivilegedExceptionAction<DatagramSocket> action = () -> new DatagramSocket(0);
int port;
try {
@SuppressWarnings({"deprecated", "removal"})
DatagramSocket ds = AccessController.doPrivileged(action);
try (DatagramSocket ds1 = ds) {
port = ds1.getLocalPort();
}
} catch (Exception x) {
port = 0;
}
return port;
}
// Records a subset of max {@code capacity} previously used ports
static final class PortHistory {
final int capacity;
@ -74,7 +91,10 @@ class DNSDatagramSocketFactory {
public boolean add(int port) {
if (ports[index] != 0) { // at max capacity
// remove one port at random and store the new port there
ports[random.nextInt(capacity)] = port;
// don't remove the last port
int remove = random.nextInt(capacity);
if ((remove +1) % capacity == index) remove = index;
ports[index = remove] = port;
} else { // there's a free slot
ports[index] = port;
}
@ -90,7 +110,8 @@ class DNSDatagramSocketFactory {
}
}
int lastport = 0;
int lastport = findFirstFreePort();
int lastSystemAllocated = lastport;
int suitablePortCount;
int unsuitablePortCount;
final ProtocolFamily family; // null (default) means dual stack
@ -147,13 +168,16 @@ class DNSDatagramSocketFactory {
s = openDefault();
lastport = s.getLocalPort();
if (lastseen == 0) {
lastSystemAllocated = lastport;
history.offer(lastport);
return s;
}
thresholdCrossed = suitablePortCount > thresholdCount;
boolean farEnough = Integer.bitCount(lastseen ^ lastport) > BIT_DEVIATION
&& Math.abs(lastport - lastseen) > deviation;
boolean farEnough = farEnough(lastseen);
if (farEnough && lastSystemAllocated > 0) {
farEnough = farEnough(lastSystemAllocated);
}
boolean recycled = history.contains(lastport);
boolean suitable = (thresholdCrossed || farEnough && !recycled);
if (suitable && !recycled) history.add(lastport);
@ -168,6 +192,7 @@ class DNSDatagramSocketFactory {
// Either the underlying stack supports random UDP port allocation,
// or the new port is sufficiently distant from last port to make
// it look like it is. Let's use it.
lastSystemAllocated = lastport;
return s;
}
@ -196,9 +221,7 @@ class DNSDatagramSocketFactory {
} catch (SocketException x) {
throw x;
} catch (IOException x) {
SocketException e = new SocketException(x.getMessage());
e.initCause(x);
throw e;
throw new SocketException(x.getMessage(), x);
}
}
return new DatagramSocket();
@ -218,24 +241,48 @@ class DNSDatagramSocketFactory {
&& !isUsingNativePortRandomization();
}
private boolean farEnough(int port) {
return Integer.bitCount(port ^ lastport) > BIT_DEVIATION
&& Math.abs(port - lastport) > deviation;
}
private DatagramSocket openRandom() {
int maxtries = MAX_RANDOM_TRIES;
while (maxtries-- > 0) {
int port = EphemeralPortRange.LOWER
+ random.nextInt(EphemeralPortRange.RANGE);
int port;
boolean suitable;
boolean recycled;
int maxrandom = MAX_RANDOM_TRIES;
do {
port = EphemeralPortRange.LOWER
+ random.nextInt(EphemeralPortRange.RANGE);
recycled = history.contains(port);
suitable = lastport == 0 || (farEnough(port) && !recycled);
} while (maxrandom-- > 0 && !suitable);
// if no suitable port was found, try again
// this means we might call random MAX_RANDOM_TRIES x MAX_RANDOM_TRIES
// times - but that should be OK with MAX_RANDOM_TRIES = 5.
if (!suitable) continue;
try {
if (family != null) {
DatagramChannel c = DatagramChannel.open(family);
try {
DatagramSocket s = c.socket();
s.bind(new InetSocketAddress(port));
lastport = s.getLocalPort();
if (!recycled) history.add(port);
return s;
} catch (Throwable x) {
c.close();
throw x;
}
}
return new DatagramSocket(port);
DatagramSocket s = new DatagramSocket(port);
lastport = s.getLocalPort();
if (!recycled) history.add(port);
return s;
} catch (IOException x) {
// try again until maxtries == 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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,21 +34,7 @@
*/
/*
* This test tests the actual swap size on linux and solaris.
* The correct value should be checked manually:
* Solaris:
* 1. In a shell, enter the command: "swap -l"
* 2. The value (reported in blocks) is in the "blocks" column.
* Linux:
* 1. In a shell, enter the command: "cat /proc/meminfo"
* 2. The value (reported in bytes) is in "Swap" entry, "total" column.
* Windows NT/XP/2000:
* 1. Run Start->Accessories->System Tools->System Information.
* 2. The value (reported in Kbytes) is in the "Page File Space" entry
* Windows 98/ME:
* Unknown.
*
* Usage: GetTotalSwapSpaceSize <expected swap size | "sanity-only"> [trace]
* This test tests the actual swap size on Linux and MacOS only.
*/
import com.sun.management.OperatingSystemMXBean;
@ -71,19 +57,31 @@ public class TestTotalSwap {
private static final long MAX_SIZE_FOR_PASS = Long.MAX_VALUE;
public static void main(String args[]) throws Throwable {
// yocto might ignore the request to report swap size in bytes
boolean swapInKB = mbean.getVersion().contains("yocto");
long expected_swap_size = getSwapSizeFromOs();
long min_size = mbean.getFreeSwapSpaceSize();
if (min_size > 0) {
min_size_for_pass = min_size;
}
long expected_swap_size = getSwapSizeFromOs();
long size = mbean.getTotalSwapSpaceSize();
System.out.println("Total swap space size in bytes: " + size);
System.out.println("Total swap space size from OS in bytes: " + expected_swap_size);
System.out.println("Total swap space size in MBean bytes: " + size);
// if swap data from OS chnaged re-read OS and MBean data
while (expected_swap_size != getSwapSizeFromOs()) {
System.out.println("Total swap space reported by OS changed form " + expected_swap_size
+ " current value = " + getSwapSizeFromOs());
expected_swap_size = getSwapSizeFromOs();
size = mbean.getTotalSwapSpaceSize();
System.out.println("Re-read total swap space size from OS in bytes: " + expected_swap_size);
System.out.println("Total swap space size in MBean bytes: " + size);
}
if (expected_swap_size > -1) {
if (size != expected_swap_size) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, 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,8 +25,8 @@
* @test
* @bug 6725892
* @library /test/lib
* @run main/othervm -Dsun.net.httpserver.maxReqTime=2 Test
* @run main/othervm -Djava.net.preferIPv6Addresses=true -Dsun.net.httpserver.maxReqTime=2 Test
* @run main/othervm -Dsun.net.httpserver.maxReqTime=2 -Dsun.net.httpserver.clockTick=2000 Test
* @run main/othervm -Djava.net.preferIPv6Addresses=true -Dsun.net.httpserver.maxReqTime=2 -Dsun.net.httpserver.clockTick=2000 Test
* @summary
*/

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8282252
* @summary Test constructors of BigDecimal to replace BigInteger subclasses
*/
import java.math.*;
public class ConstructorUnscaledValue {
public static void main(String... args) {
TestBigInteger tbi = new TestBigInteger(BigInteger.ONE);
// Create BigDecimal's using each of the three constructors
// with guards on the class of unscaledValue
BigDecimal[] values = {
new BigDecimal(tbi),
new BigDecimal(tbi, 2),
new BigDecimal(tbi, 3, MathContext.DECIMAL32),
};
for (var bd : values) {
BigInteger unscaledValue = bd.unscaledValue();
if (unscaledValue.getClass() != BigInteger.class) {
throw new RuntimeException("Bad class for unscaledValue");
}
if (!unscaledValue.equals(BigInteger.ONE)) {
throw new RuntimeException("Bad value for unscaledValue");
}
}
}
private static class TestBigInteger extends BigInteger {
public TestBigInteger(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return java.util.Arrays.toString(toByteArray());
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, 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,54 +23,128 @@
/*
* @test
* @bug 6177836
* @bug 6177836 8282252
* @summary Verify BigDecimal objects with collapsed values are serialized properly.
* @author Joseph D. Darcy
*/
import java.math.*;
import java.io.*;
import java.util.List;
public class SerializationTests {
static void checkSerialForm(BigDecimal bd) throws Exception {
public static void main(String... args) throws Exception {
checkBigDecimalSerialRoundTrip();
checkBigDecimalSubSerialRoundTrip();
}
private static void checkSerialForm(BigDecimal bd) throws Exception {
checkSerialForm0(bd);
checkSerialForm0(bd.negate());
}
private static void checkSerialForm0(BigDecimal bd) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(bd);
oos.flush();
oos.close();
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(bd);
oos.flush();
}
ObjectInputStream ois = new
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
BigDecimal tmp = (BigDecimal)ois.readObject();
if (!bd.equals(tmp) ||
bd.hashCode() != tmp.hashCode()) {
bd.hashCode() != tmp.hashCode() ||
bd.getClass() != tmp.getClass() ||
// Directly test equality of components
bd.scale() != tmp.scale() ||
!bd.unscaledValue().equals(tmp.unscaledValue())) {
System.err.print(" original : " + bd);
System.err.println(" (hash: 0x" + Integer.toHexString(bd.hashCode()) + ")");
System.err.print("serialized : " + tmp);
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
throw new RuntimeException("Bad serial roundtrip");
}
// If the class of the deserialized number is BigDecimal,
// verify the implementation constraint on the unscaled value
// having BigInteger class
if (tmp.getClass() == BigDecimal.class) {
if (tmp.unscaledValue().getClass() != BigInteger.class) {
throw new RuntimeException("Not using genuine BigInteger as an unscaled value");
}
}
}
public static void main(String[] args) throws Exception {
BigDecimal values[] = {
BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TEN,
new BigDecimal(0),
new BigDecimal(1),
new BigDecimal(10),
new BigDecimal(Integer.MAX_VALUE),
new BigDecimal(Long.MAX_VALUE-1),
new BigDecimal(BigInteger.valueOf(1), 1),
new BigDecimal(BigInteger.valueOf(100), 50),
};
private static class BigIntegerSub extends BigInteger {
public BigIntegerSub(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return java.util.Arrays.toString(toByteArray());
}
}
private static void checkBigDecimalSerialRoundTrip() throws Exception {
var values =
List.of(BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TEN,
new BigDecimal(0),
new BigDecimal(1),
new BigDecimal(10),
new BigDecimal(Integer.MAX_VALUE),
new BigDecimal(Long.MAX_VALUE-1),
new BigDecimal(BigInteger.valueOf(1), 1),
new BigDecimal(BigInteger.valueOf(100), 50),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MAX_VALUE),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MIN_VALUE),
new BigDecimal(new BigIntegerSub(BigInteger.ONE), 2));
for(BigDecimal value : values) {
checkSerialForm(value);
checkSerialForm(value.negate());
}
}
private static class BigDecimalSub extends BigDecimal {
public BigDecimalSub(BigDecimal bd) {
super(bd.unscaledValue(), bd.scale());
}
@Override
public String toString() {
return unscaledValue() + "x10^" + (-scale());
}
}
// Subclass defining a serialVersionUID
private static class BigDecimalSubSVUID extends BigDecimal {
@java.io.Serial
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
public BigDecimalSubSVUID(BigDecimal bd) {
super(bd.unscaledValue(), bd.scale());
}
}
private static void checkBigDecimalSubSerialRoundTrip() throws Exception {
var values =
List.of(BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TEN,
new BigDecimal(BigInteger.TEN, 1234),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MAX_VALUE),
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
Integer.MIN_VALUE));
for(var value : values) {
checkSerialForm(new BigDecimalSub(value));
checkSerialForm(new BigDecimalSubSVUID(value));
}
}
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2005, 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8282252
* @summary Verify BigInteger objects are serialized properly.
*/
import java.math.*;
import java.io.*;
import java.util.Arrays;
import java.util.List;
public class SerializationTests {
public static void main(String... args) throws Exception {
checkBigIntegerSerialRoundTrip();
checkBigIntegerSubSerialRoundTrip();
}
private static void checkSerialForm(BigInteger bi) throws Exception {
checkSerialForm0(bi);
checkSerialForm0(bi.negate());
}
private static void checkSerialForm0(BigInteger bi) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(bi);
oos.flush();
}
ObjectInputStream ois = new
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
BigInteger tmp = (BigInteger)ois.readObject();
if (!bi.equals(tmp) ||
bi.hashCode() != tmp.hashCode() ||
bi.getClass() != tmp.getClass() ||
// For extra measure, directly test equality of components
bi.signum() != tmp.signum() ||
!Arrays.equals(bi.toByteArray(), (tmp.toByteArray())) ) {
System.err.print(" original : " + bi);
System.err.println(" (hash: 0x" + Integer.toHexString(bi.hashCode()) + ")");
System.err.print("serialized : " + tmp);
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
throw new RuntimeException("Bad serial roundtrip");
}
}
private static void checkBigIntegerSerialRoundTrip() throws Exception {
var values =
List.of(BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TWO,
BigInteger.TEN,
BigInteger.valueOf(100),
BigInteger.valueOf(Integer.MAX_VALUE),
BigInteger.valueOf(Long.MAX_VALUE-1),
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
for(BigInteger value : values) {
checkSerialForm(value);
}
}
// Subclass with specialized toString output
private static class BigIntegerSub extends BigInteger {
public BigIntegerSub(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return Arrays.toString(toByteArray());
}
}
// Subclass defining a serialVersionUID
private static class BigIntegerSubSVUID extends BigInteger {
@java.io.Serial
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
public BigIntegerSubSVUID(BigInteger bi) {
super(bi.toByteArray());
}
@Override
public String toString() {
return Arrays.toString(toByteArray());
}
}
// Subclass defining writeReplace
private static class BigIntegerSubWR extends BigInteger {
public BigIntegerSubWR(BigInteger bi) {
super(bi.toByteArray());
}
// Just return this; could use a serial proxy instead
@java.io.Serial
private Object writeReplace() throws ObjectStreamException {
return this;
}
}
private static void checkBigIntegerSubSerialRoundTrip() throws Exception {
var values = List.of(BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TEN,
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
for(var value : values) {
checkSerialForm(new BigIntegerSub(value));
checkSerialForm(new BigIntegerSubSVUID(value));
checkSerialForm(new BigIntegerSubWR(value));
}
}
}

View File

@ -457,7 +457,7 @@ public class ConnectionPoolTest {
InetSocketAddress proxy,
boolean secured) {
super(address, impl);
this.key = ConnectionPool.cacheKey(address, proxy);
this.key = ConnectionPool.cacheKey(secured, address, proxy);
this.address = address;
this.proxy = proxy;
this.secured = secured;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, 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 8151788
* @bug 8151788 8286526
* @summary NullPointerException from ntlm.Client.type3
* @modules java.base/com.sun.security.ntlm
* @run main NULLTargetInfoTest
@ -42,7 +42,7 @@ public class NULLTargetInfoTest {
"4E 54 4C 4D 53 53 50 00 02 00 00 00 00 00 00 00"
+ "00 00 00 00 05 82 89 00 0B 87 81 B6 2D 6E 8B C1"
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
byte[] nonce = new byte[10];
byte[] nonce = new byte[8];
c.type3(type2, nonce);
}