mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 03:43:21 +00:00
Merge
This commit is contained in:
commit
51d5164ca2
1
.hgtags
1
.hgtags
@ -610,4 +610,5 @@ d54ce919da90dab361995bb4d87be9851f00537a jdk-14+30
|
||||
bb0a7975b31ded63d594ee8dbfc4d4ead587f79b jdk-15+4
|
||||
decd3d2953b640f1043ee76953ff89238bff92e8 jdk-14+31
|
||||
b97c1773ccafae4a8c16cc6aedb10b2a4f9a07ed jdk-15+5
|
||||
2776da28515e087cc8849acf1e131a65ea7e77b6 jdk-14+32
|
||||
ef7d53b4fccd4a0501b17d974e84f37aa99fa813 jdk-15+6
|
||||
|
||||
@ -291,23 +291,26 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
|
||||
int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) {
|
||||
InstanceKlass* superk = initialsuper;
|
||||
while (superk != NULL && superk->super() != NULL) {
|
||||
InstanceKlass* supersuperklass = InstanceKlass::cast(superk->super());
|
||||
klassVtable ssVtable = supersuperklass->vtable();
|
||||
klassVtable ssVtable = (superk->super())->vtable();
|
||||
if (vtable_index < ssVtable.length()) {
|
||||
Method* super_method = ssVtable.method_at(vtable_index);
|
||||
// get the class holding the matching method
|
||||
// make sure you use that class for is_override
|
||||
InstanceKlass* supermethodholder = super_method->method_holder();
|
||||
#ifndef PRODUCT
|
||||
Symbol* name= target_method()->name();
|
||||
Symbol* signature = target_method()->signature();
|
||||
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
|
||||
#endif
|
||||
if (supersuperklass->is_override(methodHandle(THREAD, super_method), target_loader, target_classname, THREAD)) {
|
||||
|
||||
if (supermethodholder->is_override(methodHandle(THREAD, super_method), target_loader, target_classname, THREAD)) {
|
||||
if (log_develop_is_enabled(Trace, vtables)) {
|
||||
ResourceMark rm(THREAD);
|
||||
LogTarget(Trace, vtables) lt;
|
||||
LogStream ls(lt);
|
||||
char* sig = target_method()->name_and_sig_as_C_string();
|
||||
ls.print("transitive overriding superclass %s with %s index %d, original flags: ",
|
||||
supersuperklass->internal_name(),
|
||||
supermethodholder->internal_name(),
|
||||
sig, vtable_index);
|
||||
super_method->print_linkage_flags(&ls);
|
||||
ls.print("overriders flags: ");
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
@ -73,7 +74,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
private static final class PrivateKeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
byte[] protectedKey;
|
||||
Certificate chain[];
|
||||
Certificate[] chain;
|
||||
};
|
||||
|
||||
// Secret key
|
||||
@ -742,23 +743,11 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
entry.date = new Date(dis.readLong());
|
||||
|
||||
// read the private key
|
||||
try {
|
||||
entry.protectedKey = new byte[dis.readInt()];
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new IOException("Keysize too big");
|
||||
}
|
||||
dis.readFully(entry.protectedKey);
|
||||
entry.protectedKey = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
|
||||
// read the certificate chain
|
||||
int numOfCerts = dis.readInt();
|
||||
try {
|
||||
if (numOfCerts > 0) {
|
||||
entry.chain = new Certificate[numOfCerts];
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new IOException("Too many certificates in "
|
||||
+ "chain");
|
||||
}
|
||||
List<Certificate> tmpCerts = new ArrayList<>();
|
||||
for (int j = 0; j < numOfCerts; j++) {
|
||||
if (xVersion == 2) {
|
||||
// read the certificate type, and instantiate a
|
||||
@ -766,27 +755,24 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
// existing factory if possible)
|
||||
String certType = dis.readUTF();
|
||||
if (cfs.containsKey(certType)) {
|
||||
// reuse certificate factory
|
||||
// reuse certificate factory
|
||||
cf = cfs.get(certType);
|
||||
} else {
|
||||
// create new certificate factory
|
||||
// create new certificate factory
|
||||
cf = CertificateFactory.getInstance(
|
||||
certType);
|
||||
// store the certificate factory so we can
|
||||
// reuse it later
|
||||
// store the certificate factory so we can
|
||||
// reuse it later
|
||||
cfs.put(certType, cf);
|
||||
}
|
||||
}
|
||||
// instantiate the certificate
|
||||
try {
|
||||
encoded = new byte[dis.readInt()];
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new IOException("Certificate too big");
|
||||
}
|
||||
dis.readFully(encoded);
|
||||
encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
bais = new ByteArrayInputStream(encoded);
|
||||
entry.chain[j] = cf.generateCertificate(bais);
|
||||
tmpCerts.add(cf.generateCertificate(bais));
|
||||
}
|
||||
entry.chain = tmpCerts.toArray(
|
||||
new Certificate[numOfCerts]);
|
||||
|
||||
// Add the entry to the list
|
||||
entries.put(alias, entry);
|
||||
@ -818,12 +804,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
cfs.put(certType, cf);
|
||||
}
|
||||
}
|
||||
try {
|
||||
encoded = new byte[dis.readInt()];
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new IOException("Certificate too big");
|
||||
}
|
||||
dis.readFully(encoded);
|
||||
encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
bais = new ByteArrayInputStream(encoded);
|
||||
entry.cert = cf.generateCertificate(bais);
|
||||
|
||||
@ -882,18 +863,14 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
* with
|
||||
*/
|
||||
if (password != null) {
|
||||
byte computed[], actual[];
|
||||
computed = md.digest();
|
||||
actual = new byte[computed.length];
|
||||
dis.readFully(actual);
|
||||
for (int i = 0; i < computed.length; i++) {
|
||||
if (computed[i] != actual[i]) {
|
||||
throw new IOException(
|
||||
byte[] computed = md.digest();
|
||||
byte[] actual = IOUtils.readExactlyNBytes(dis, computed.length);
|
||||
if (!MessageDigest.isEqual(computed, actual)) {
|
||||
throw new IOException(
|
||||
"Keystore was tampered with, or "
|
||||
+ "password was incorrect",
|
||||
new UnrecoverableKeyException(
|
||||
"Password verification failed"));
|
||||
}
|
||||
new UnrecoverableKeyException(
|
||||
"Password verification failed"));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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 jdk.internal.access;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
/**
|
||||
* Interface to specify methods for accessing {@code ObjectInputStream}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface JavaObjectInputStreamReadString {
|
||||
String readString(ObjectInputStream ois) throws IOException;
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ public class SharedSecrets {
|
||||
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
||||
private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
|
||||
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
|
||||
private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
|
||||
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
|
||||
private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
|
||||
private static JavaNetInetAddressAccess javaNetInetAddressAccess;
|
||||
@ -283,6 +284,17 @@ public class SharedSecrets {
|
||||
javaUtilResourceBundleAccess = access;
|
||||
}
|
||||
|
||||
public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
|
||||
if (javaObjectInputStreamReadString == null) {
|
||||
unsafe.ensureClassInitialized(ObjectInputStream.class);
|
||||
}
|
||||
return javaObjectInputStreamReadString;
|
||||
}
|
||||
|
||||
public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
|
||||
javaObjectInputStreamReadString = access;
|
||||
}
|
||||
|
||||
public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
|
||||
if (javaObjectInputStreamAccess == null) {
|
||||
unsafe.ensureClassInitialized(ObjectInputStream.class);
|
||||
|
||||
@ -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
|
||||
@ -42,6 +42,7 @@ public final class StaticProperty {
|
||||
private static final String USER_HOME = initProperty("user.home");
|
||||
private static final String USER_DIR = initProperty("user.dir");
|
||||
private static final String USER_NAME = initProperty("user.name");
|
||||
private static final String JDK_SERIAL_FILTER = System.getProperty("jdk.serialFilter");
|
||||
|
||||
private StaticProperty() {}
|
||||
|
||||
@ -104,4 +105,17 @@ public final class StaticProperty {
|
||||
public static String userName() {
|
||||
return USER_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@code jdk.serialFilter} system property.
|
||||
*
|
||||
* <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
|
||||
* in this method. The caller of this method should take care to ensure
|
||||
* that the returned property is not made accessible to untrusted code.</strong>
|
||||
*
|
||||
* @return the {@code user.name} system property
|
||||
*/
|
||||
public static String jdkSerialFilter() {
|
||||
return JDK_SERIAL_FILTER;
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,7 +697,7 @@ public abstract class JavaKeyStore extends KeyStoreSpi {
|
||||
|
||||
// Read the private key
|
||||
entry.protectedPrivKey =
|
||||
IOUtils.readFully(dis, dis.readInt(), true);
|
||||
IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
|
||||
// Read the certificate chain
|
||||
int numOfCerts = dis.readInt();
|
||||
@ -722,7 +722,7 @@ public abstract class JavaKeyStore extends KeyStoreSpi {
|
||||
}
|
||||
}
|
||||
// instantiate the certificate
|
||||
encoded = IOUtils.readFully(dis, dis.readInt(), true);
|
||||
encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
bais = new ByteArrayInputStream(encoded);
|
||||
certs.add(cf.generateCertificate(bais));
|
||||
bais.close();
|
||||
@ -761,7 +761,7 @@ public abstract class JavaKeyStore extends KeyStoreSpi {
|
||||
cfs.put(certType, cf);
|
||||
}
|
||||
}
|
||||
encoded = IOUtils.readFully(dis, dis.readInt(), true);
|
||||
encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
bais = new ByteArrayInputStream(encoded);
|
||||
entry.cert = cf.generateCertificate(bais);
|
||||
bais.close();
|
||||
@ -787,16 +787,13 @@ public abstract class JavaKeyStore extends KeyStoreSpi {
|
||||
*/
|
||||
if (password != null) {
|
||||
byte[] computed = md.digest();
|
||||
byte[] actual = new byte[computed.length];
|
||||
dis.readFully(actual);
|
||||
for (int i = 0; i < computed.length; i++) {
|
||||
if (computed[i] != actual[i]) {
|
||||
Throwable t = new UnrecoverableKeyException
|
||||
byte[] actual = IOUtils.readExactlyNBytes(dis, computed.length);
|
||||
if (!MessageDigest.isEqual(computed, actual)) {
|
||||
Throwable t = new UnrecoverableKeyException
|
||||
("Password verification failed");
|
||||
throw (IOException)new IOException
|
||||
throw (IOException) new IOException
|
||||
("Keystore was tampered with, or "
|
||||
+ "password was incorrect").initCause(t);
|
||||
}
|
||||
+ "password was incorrect").initCause(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,8 +271,14 @@ enum Alert {
|
||||
ClientAuthType.CLIENT_AUTH_REQUESTED)) {
|
||||
throw tc.fatal(Alert.HANDSHAKE_FAILURE,
|
||||
"received handshake warning: " + alert.description);
|
||||
} // Otherwise, ignore the warning
|
||||
} // Otherwise, ignore the warning.
|
||||
} else {
|
||||
// Otherwise ignore the warning but remove the
|
||||
// CertificateVerify handshake consumer so the state
|
||||
// machine doesn't expect it.
|
||||
tc.handshakeContext.handshakeConsumers.remove(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
}
|
||||
} // Otherwise, ignore the warning
|
||||
} else { // fatal or unknown
|
||||
String diagnostic;
|
||||
if (alert == null) {
|
||||
|
||||
@ -371,6 +371,10 @@ final class CertificateMessage {
|
||||
T12CertificateMessage certificateMessage )throws IOException {
|
||||
List<byte[]> encodedCerts = certificateMessage.encodedCertChain;
|
||||
if (encodedCerts == null || encodedCerts.isEmpty()) {
|
||||
// For empty Certificate messages, we should not expect
|
||||
// a CertificateVerify message to follow
|
||||
shc.handshakeConsumers.remove(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
if (shc.sslConfig.clientAuthType !=
|
||||
ClientAuthType.CLIENT_AUTH_REQUESTED) {
|
||||
// unexpected or require client authentication
|
||||
@ -1165,6 +1169,10 @@ final class CertificateMessage {
|
||||
T13CertificateMessage certificateMessage )throws IOException {
|
||||
if (certificateMessage.certEntries == null ||
|
||||
certificateMessage.certEntries.isEmpty()) {
|
||||
// For empty Certificate messages, we should not expect
|
||||
// a CertificateVerify message to follow
|
||||
shc.handshakeConsumers.remove(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) {
|
||||
throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,
|
||||
"Empty client certificate chain");
|
||||
|
||||
@ -287,6 +287,17 @@ final class CertificateVerify {
|
||||
ByteBuffer message) throws IOException {
|
||||
// The consuming happens in server side only.
|
||||
ServerHandshakeContext shc = (ServerHandshakeContext)context;
|
||||
|
||||
// Clean up this consumer
|
||||
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
|
||||
// Ensure that the CV message follows the CKE
|
||||
if (shc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected CertificateVerify handshake message");
|
||||
}
|
||||
|
||||
S30CertificateVerifyMessage cvm =
|
||||
new S30CertificateVerifyMessage(shc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
@ -529,6 +540,17 @@ final class CertificateVerify {
|
||||
ByteBuffer message) throws IOException {
|
||||
// The consuming happens in server side only.
|
||||
ServerHandshakeContext shc = (ServerHandshakeContext)context;
|
||||
|
||||
// Clean up this consumer
|
||||
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
|
||||
// Ensure that the CV message follows the CKE
|
||||
if (shc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected CertificateVerify handshake message");
|
||||
}
|
||||
|
||||
T10CertificateVerifyMessage cvm =
|
||||
new T10CertificateVerifyMessage(shc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
@ -767,6 +789,17 @@ final class CertificateVerify {
|
||||
ByteBuffer message) throws IOException {
|
||||
// The consuming happens in server side only.
|
||||
ServerHandshakeContext shc = (ServerHandshakeContext)context;
|
||||
|
||||
// Clean up this consumer
|
||||
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
|
||||
// Ensure that the CV message follows the CKE
|
||||
if (shc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected CertificateVerify handshake message");
|
||||
}
|
||||
|
||||
T12CertificateVerifyMessage cvm =
|
||||
new T12CertificateVerifyMessage(shc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
@ -1120,6 +1153,10 @@ final class CertificateVerify {
|
||||
ByteBuffer message) throws IOException {
|
||||
// The producing happens in handshake context only.
|
||||
HandshakeContext hc = (HandshakeContext)context;
|
||||
|
||||
// Clean up this consumer
|
||||
hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
|
||||
|
||||
T13CertificateVerifyMessage cvm =
|
||||
new T13CertificateVerifyMessage(hc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
|
||||
@ -1140,6 +1140,15 @@ final class ClientHello {
|
||||
ServerHandshakeContext shc = (ServerHandshakeContext)context;
|
||||
ClientHelloMessage clientHello = (ClientHelloMessage)message;
|
||||
|
||||
// [RFC 8446] TLS 1.3 forbids renegotiation. If a server has
|
||||
// negotiated TLS 1.3 and receives a ClientHello at any other
|
||||
// time, it MUST terminate the connection with an
|
||||
// "unexpected_message" alert.
|
||||
if (shc.conContext.isNegotiated) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Received unexpected renegotiation handshake message");
|
||||
}
|
||||
|
||||
// The client may send a dummy change_cipher_spec record
|
||||
// immediately after the first ClientHello.
|
||||
shc.conContext.consumers.putIfAbsent(
|
||||
|
||||
@ -589,6 +589,16 @@ final class Finished {
|
||||
|
||||
private void onConsumeFinished(ServerHandshakeContext shc,
|
||||
ByteBuffer message) throws IOException {
|
||||
// Make sure that any expected CertificateVerify message
|
||||
// has been received and processed.
|
||||
if (!shc.isResumption) {
|
||||
if (shc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id)) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected Finished handshake message");
|
||||
}
|
||||
}
|
||||
|
||||
FinishedMessage fm = new FinishedMessage(shc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
@ -883,6 +893,16 @@ final class Finished {
|
||||
|
||||
private void onConsumeFinished(ClientHandshakeContext chc,
|
||||
ByteBuffer message) throws IOException {
|
||||
// Make sure that any expected CertificateVerify message
|
||||
// has been received and processed.
|
||||
if (!chc.isResumption) {
|
||||
if (chc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id)) {
|
||||
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected Finished handshake message");
|
||||
}
|
||||
}
|
||||
|
||||
FinishedMessage fm = new FinishedMessage(chc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
@ -1005,6 +1025,16 @@ final class Finished {
|
||||
|
||||
private void onConsumeFinished(ServerHandshakeContext shc,
|
||||
ByteBuffer message) throws IOException {
|
||||
// Make sure that any expected CertificateVerify message
|
||||
// has been received and processed.
|
||||
if (!shc.isResumption) {
|
||||
if (shc.handshakeConsumers.containsKey(
|
||||
SSLHandshake.CERTIFICATE_VERIFY.id)) {
|
||||
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unexpected Finished handshake message");
|
||||
}
|
||||
}
|
||||
|
||||
FinishedMessage fm = new FinishedMessage(shc, message);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
|
||||
@ -395,7 +395,7 @@ public class DerValue {
|
||||
if (fullyBuffered && in.available() != length)
|
||||
throw new IOException("extra data given to DerValue constructor");
|
||||
|
||||
byte[] bytes = IOUtils.readFully(in, length, true);
|
||||
byte[] bytes = IOUtils.readExactlyNBytes(in, length);
|
||||
|
||||
buffer = new DerInputBuffer(bytes, allowBER);
|
||||
return new DerInputStream(buffer);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 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
|
||||
@ -32,68 +32,34 @@ package sun.security.util;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class IOUtils {
|
||||
|
||||
/**
|
||||
* Read up to {@code length} of bytes from {@code in}
|
||||
* until EOF is detected.
|
||||
* @param is input stream, must not be null
|
||||
* @param length number of bytes to read
|
||||
* @param readAll if true, an EOFException will be thrown if not enough
|
||||
* bytes are read.
|
||||
* @return bytes read
|
||||
* @throws IOException Any IO error or a premature EOF is detected
|
||||
*/
|
||||
public static byte[] readFully(InputStream is, int length, boolean readAll)
|
||||
throws IOException {
|
||||
if (length < 0) {
|
||||
throw new IOException("Invalid length");
|
||||
}
|
||||
byte[] output = {};
|
||||
int pos = 0;
|
||||
while (pos < length) {
|
||||
int bytesToRead;
|
||||
if (pos >= output.length) { // Only expand when there's no room
|
||||
bytesToRead = Math.min(length - pos, output.length + 1024);
|
||||
if (output.length < pos + bytesToRead) {
|
||||
output = Arrays.copyOf(output, pos + bytesToRead);
|
||||
}
|
||||
} else {
|
||||
bytesToRead = output.length - pos;
|
||||
}
|
||||
int cc = is.read(output, pos, bytesToRead);
|
||||
if (cc < 0) {
|
||||
if (readAll) {
|
||||
throw new EOFException("Detect premature EOF");
|
||||
} else {
|
||||
if (output.length != pos) {
|
||||
output = Arrays.copyOf(output, pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos += cc;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read {@code length} of bytes from {@code in}. An exception is
|
||||
* thrown if there are not enough bytes in the stream.
|
||||
* Read exactly {@code length} of bytes from {@code in}.
|
||||
*
|
||||
* <p> Note that this method is safe to be called with unknown large
|
||||
* {@code length} argument. The memory used is proportional to the
|
||||
* actual bytes available. An exception is thrown if there are not
|
||||
* enough bytes in the stream.
|
||||
*
|
||||
* @param is input stream, must not be null
|
||||
* @param length number of bytes to read, must not be negative
|
||||
* @param length number of bytes to read
|
||||
* @return bytes read
|
||||
* @throws IOException if any IO error or a premature EOF is detected, or
|
||||
* if {@code length} is negative since this length is usually also
|
||||
* read from {@code is}.
|
||||
* @throws EOFException if there are not enough bytes in the stream
|
||||
* @throws IOException if an I/O error occurs or {@code length} is negative
|
||||
* @throws OutOfMemoryError if an array of the required size cannot be
|
||||
* allocated.
|
||||
*/
|
||||
public static byte[] readNBytes(InputStream is, int length) throws IOException {
|
||||
public static byte[] readExactlyNBytes(InputStream is, int length)
|
||||
throws IOException {
|
||||
if (length < 0) {
|
||||
throw new IOException("length cannot be negative: " + length);
|
||||
}
|
||||
return readFully(is, length, true);
|
||||
byte[] data = is.readNBytes(length);
|
||||
if (data.length < length) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import java.security.cert.*;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.provider.certpath.AlgorithmChecker;
|
||||
import sun.security.provider.certpath.PKIXExtendedParameters;
|
||||
|
||||
@ -60,6 +61,18 @@ public final class PKIXValidator extends Validator {
|
||||
private static final boolean checkTLSRevocation = GetBooleanAction
|
||||
.privilegedGetProperty("com.sun.net.ssl.checkRevocation");
|
||||
|
||||
/**
|
||||
* System property that if set (or set to "true"), allows trust anchor
|
||||
* certificates to be used if they do not have the proper CA extensions.
|
||||
* Set to false if prop is not set, or set to any other value.
|
||||
*/
|
||||
private static final boolean ALLOW_NON_CA_ANCHOR = allowNonCaAnchor();
|
||||
private static boolean allowNonCaAnchor() {
|
||||
String prop = GetPropertyAction
|
||||
.privilegedGetProperty("jdk.security.allowNonCaAnchor");
|
||||
return prop != null && (prop.isEmpty() || prop.equalsIgnoreCase("true"));
|
||||
}
|
||||
|
||||
private final Set<X509Certificate> trustedCerts;
|
||||
private final PKIXBuilderParameters parameterTemplate;
|
||||
private int certPathLength = -1;
|
||||
@ -195,6 +208,7 @@ public final class PKIXValidator extends Validator {
|
||||
("null or zero-length certificate chain");
|
||||
}
|
||||
|
||||
|
||||
// Use PKIXExtendedParameters for timestamp and variant additions
|
||||
PKIXBuilderParameters pkixParameters = null;
|
||||
try {
|
||||
@ -224,28 +238,30 @@ public final class PKIXValidator extends Validator {
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
X509Certificate cert = chain[i];
|
||||
X500Principal dn = cert.getSubjectX500Principal();
|
||||
if (i != 0 && !dn.equals(prevIssuer)) {
|
||||
// chain is not ordered correctly, call builder instead
|
||||
return doBuild(chain, otherCerts, pkixParameters);
|
||||
}
|
||||
|
||||
// Check if chain[i] is already trusted. It may be inside
|
||||
// trustedCerts, or has the same dn and public key as a cert
|
||||
// inside trustedCerts. The latter happens when a CA has
|
||||
// updated its cert with a stronger signature algorithm in JRE
|
||||
// but the weak one is still in circulation.
|
||||
|
||||
if (trustedCerts.contains(cert) || // trusted cert
|
||||
(trustedSubjects.containsKey(dn) && // replacing ...
|
||||
trustedSubjects.get(dn).contains( // ... weak cert
|
||||
cert.getPublicKey()))) {
|
||||
if (i == 0) {
|
||||
if (i == 0) {
|
||||
if (trustedCerts.contains(cert)) {
|
||||
return new X509Certificate[] {chain[0]};
|
||||
}
|
||||
// Remove and call validator on partial chain [0 .. i-1]
|
||||
X509Certificate[] newChain = new X509Certificate[i];
|
||||
System.arraycopy(chain, 0, newChain, 0, i);
|
||||
return doValidate(newChain, pkixParameters);
|
||||
} else {
|
||||
if (!dn.equals(prevIssuer)) {
|
||||
// chain is not ordered correctly, call builder instead
|
||||
return doBuild(chain, otherCerts, pkixParameters);
|
||||
}
|
||||
// Check if chain[i] is already trusted. It may be inside
|
||||
// trustedCerts, or has the same dn and public key as a cert
|
||||
// inside trustedCerts. The latter happens when a CA has
|
||||
// updated its cert with a stronger signature algorithm in JRE
|
||||
// but the weak one is still in circulation.
|
||||
if (trustedCerts.contains(cert) || // trusted cert
|
||||
(trustedSubjects.containsKey(dn) && // replacing ...
|
||||
trustedSubjects.get(dn).contains( // ... weak cert
|
||||
cert.getPublicKey()))) {
|
||||
// Remove and call validator on partial chain [0 .. i-1]
|
||||
X509Certificate[] newChain = new X509Certificate[i];
|
||||
System.arraycopy(chain, 0, newChain, 0, i);
|
||||
return doValidate(newChain, pkixParameters);
|
||||
}
|
||||
}
|
||||
prevIssuer = cert.getIssuerX500Principal();
|
||||
}
|
||||
@ -308,15 +324,18 @@ public final class PKIXValidator extends Validator {
|
||||
|
||||
private static X509Certificate[] toArray(CertPath path, TrustAnchor anchor)
|
||||
throws CertificateException {
|
||||
List<? extends java.security.cert.Certificate> list =
|
||||
path.getCertificates();
|
||||
X509Certificate[] chain = new X509Certificate[list.size() + 1];
|
||||
list.toArray(chain);
|
||||
X509Certificate trustedCert = anchor.getTrustedCert();
|
||||
if (trustedCert == null) {
|
||||
throw new ValidatorException
|
||||
("TrustAnchor must be specified as certificate");
|
||||
}
|
||||
|
||||
verifyTrustAnchor(trustedCert);
|
||||
|
||||
List<? extends java.security.cert.Certificate> list =
|
||||
path.getCertificates();
|
||||
X509Certificate[] chain = new X509Certificate[list.size() + 1];
|
||||
list.toArray(chain);
|
||||
chain[chain.length - 1] = trustedCert;
|
||||
return chain;
|
||||
}
|
||||
@ -351,6 +370,41 @@ public final class PKIXValidator extends Validator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a trust anchor certificate is a CA certificate.
|
||||
*/
|
||||
private static void verifyTrustAnchor(X509Certificate trustedCert)
|
||||
throws ValidatorException {
|
||||
|
||||
// skip check if jdk.security.allowNonCAAnchor system property is set
|
||||
if (ALLOW_NON_CA_ANCHOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
// allow v1 trust anchor certificates
|
||||
if (trustedCert.getVersion() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check that the BasicConstraints cA field is not set to false
|
||||
if (trustedCert.getBasicConstraints() == -1) {
|
||||
throw new ValidatorException
|
||||
("TrustAnchor with subject \"" +
|
||||
trustedCert.getSubjectX500Principal() +
|
||||
"\" is not a CA certificate");
|
||||
}
|
||||
|
||||
// check that the KeyUsage extension, if included, asserts the
|
||||
// keyCertSign bit
|
||||
boolean[] keyUsageBits = trustedCert.getKeyUsage();
|
||||
if (keyUsageBits != null && !keyUsageBits[5]) {
|
||||
throw new ValidatorException
|
||||
("TrustAnchor with subject \"" +
|
||||
trustedCert.getSubjectX500Principal() +
|
||||
"\" does not have keyCertSign bit set in KeyUsage extension");
|
||||
}
|
||||
}
|
||||
|
||||
private X509Certificate[] doBuild(X509Certificate[] chain,
|
||||
Collection<X509Certificate> otherCerts,
|
||||
PKIXBuilderParameters params) throws CertificateException {
|
||||
|
||||
@ -599,7 +599,7 @@ public class AVA implements DerEncoder {
|
||||
if (derval.tag != DerValue.tag_Sequence) {
|
||||
throw new IOException("AVA not a sequence");
|
||||
}
|
||||
oid = X500Name.intern(derval.data.getOID());
|
||||
oid = derval.data.getOID();
|
||||
value = derval.data.getDerValue();
|
||||
|
||||
if (derval.data.available() != 0) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -1097,18 +1097,6 @@ public class X500Name implements GeneralNameInterface, Principal {
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
/*
|
||||
* Maybe return a preallocated OID, to reduce storage costs
|
||||
* and speed recognition of common X.500 attributes.
|
||||
*/
|
||||
static ObjectIdentifier intern(ObjectIdentifier oid) {
|
||||
ObjectIdentifier interned = internedOIDs.putIfAbsent(oid, oid);
|
||||
return (interned == null) ? oid : interned;
|
||||
}
|
||||
|
||||
private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs
|
||||
= new HashMap<ObjectIdentifier,ObjectIdentifier>();
|
||||
|
||||
/*
|
||||
* Selected OIDs from X.520
|
||||
* Includes all those specified in RFC 5280 as MUST or SHOULD
|
||||
@ -1136,92 +1124,82 @@ public class X500Name implements GeneralNameInterface, Principal {
|
||||
{ 0, 9, 2342, 19200300, 100, 1, 1 };
|
||||
|
||||
|
||||
public static final ObjectIdentifier commonName_oid;
|
||||
public static final ObjectIdentifier countryName_oid;
|
||||
public static final ObjectIdentifier localityName_oid;
|
||||
public static final ObjectIdentifier orgName_oid;
|
||||
public static final ObjectIdentifier orgUnitName_oid;
|
||||
public static final ObjectIdentifier stateName_oid;
|
||||
public static final ObjectIdentifier streetAddress_oid;
|
||||
public static final ObjectIdentifier title_oid;
|
||||
public static final ObjectIdentifier DNQUALIFIER_OID;
|
||||
public static final ObjectIdentifier SURNAME_OID;
|
||||
public static final ObjectIdentifier GIVENNAME_OID;
|
||||
public static final ObjectIdentifier INITIALS_OID;
|
||||
public static final ObjectIdentifier GENERATIONQUALIFIER_OID;
|
||||
public static final ObjectIdentifier ipAddress_oid;
|
||||
public static final ObjectIdentifier DOMAIN_COMPONENT_OID;
|
||||
public static final ObjectIdentifier userid_oid;
|
||||
public static final ObjectIdentifier SERIALNUMBER_OID;
|
||||
// OID for the "CN=" attribute, denoting a person's common name.
|
||||
public static final ObjectIdentifier commonName_oid =
|
||||
ObjectIdentifier.newInternal(commonName_data);
|
||||
|
||||
static {
|
||||
/** OID for the "CN=" attribute, denoting a person's common name. */
|
||||
commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data));
|
||||
// OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
|
||||
// a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
|
||||
// certificate serial number.
|
||||
public static final ObjectIdentifier SERIALNUMBER_OID =
|
||||
ObjectIdentifier.newInternal(SERIALNUMBER_DATA);
|
||||
|
||||
/** OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
|
||||
a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
|
||||
certificate serial number. */
|
||||
SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA));
|
||||
// OID for the "C=" attribute, denoting a country.
|
||||
public static final ObjectIdentifier countryName_oid =
|
||||
ObjectIdentifier.newInternal(countryName_data);
|
||||
|
||||
/** OID for the "C=" attribute, denoting a country. */
|
||||
countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data));
|
||||
// OID for the "L=" attribute, denoting a locality (such as a city).
|
||||
public static final ObjectIdentifier localityName_oid =
|
||||
ObjectIdentifier.newInternal(localityName_data);
|
||||
|
||||
/** OID for the "L=" attribute, denoting a locality (such as a city) */
|
||||
localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data));
|
||||
// OID for the "O=" attribute, denoting an organization name.
|
||||
public static final ObjectIdentifier orgName_oid =
|
||||
ObjectIdentifier.newInternal(orgName_data);
|
||||
|
||||
/** OID for the "O=" attribute, denoting an organization name */
|
||||
orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data));
|
||||
// OID for the "OU=" attribute, denoting an organizational unit name.
|
||||
public static final ObjectIdentifier orgUnitName_oid =
|
||||
ObjectIdentifier.newInternal(orgUnitName_data);
|
||||
|
||||
/** OID for the "OU=" attribute, denoting an organizational unit name */
|
||||
orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data));
|
||||
// OID for the "S=" attribute, denoting a state (such as Delaware).
|
||||
public static final ObjectIdentifier stateName_oid =
|
||||
ObjectIdentifier.newInternal(stateName_data);
|
||||
|
||||
/** OID for the "S=" attribute, denoting a state (such as Delaware) */
|
||||
stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data));
|
||||
// OID for the "STREET=" attribute, denoting a street address.
|
||||
public static final ObjectIdentifier streetAddress_oid =
|
||||
ObjectIdentifier.newInternal(streetAddress_data);
|
||||
|
||||
/** OID for the "STREET=" attribute, denoting a street address. */
|
||||
streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data));
|
||||
// OID for the "T=" attribute, denoting a person's title.
|
||||
public static final ObjectIdentifier title_oid =
|
||||
ObjectIdentifier.newInternal(title_data);
|
||||
|
||||
/** OID for the "T=" attribute, denoting a person's title. */
|
||||
title_oid = intern(ObjectIdentifier.newInternal(title_data));
|
||||
// OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
|
||||
// disambiguating information.
|
||||
public static final ObjectIdentifier DNQUALIFIER_OID =
|
||||
ObjectIdentifier.newInternal(DNQUALIFIER_DATA);
|
||||
|
||||
/** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
|
||||
disambiguating information.*/
|
||||
DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA));
|
||||
// OID for the "SURNAME=" attribute, denoting a person's surname.
|
||||
public static final ObjectIdentifier SURNAME_OID =
|
||||
ObjectIdentifier.newInternal(SURNAME_DATA);
|
||||
|
||||
/** OID for the "SURNAME=" attribute, denoting a person's surname.*/
|
||||
SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA));
|
||||
// OID for the "GIVENNAME=" attribute, denoting a person's given name.
|
||||
public static final ObjectIdentifier GIVENNAME_OID =
|
||||
ObjectIdentifier.newInternal(GIVENNAME_DATA);
|
||||
|
||||
/** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
|
||||
GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA));
|
||||
// OID for the "INITIALS=" attribute, denoting a person's initials.
|
||||
public static final ObjectIdentifier INITIALS_OID =
|
||||
ObjectIdentifier.newInternal(INITIALS_DATA);
|
||||
|
||||
/** OID for the "INITIALS=" attribute, denoting a person's initials.*/
|
||||
INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA));
|
||||
// OID for the "GENERATION=" attribute, denoting Jr., II, etc.
|
||||
public static final ObjectIdentifier GENERATIONQUALIFIER_OID =
|
||||
ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA);
|
||||
|
||||
/** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
|
||||
GENERATIONQUALIFIER_OID =
|
||||
intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA));
|
||||
// OIDs from other sources which show up in X.500 names we
|
||||
// expect to deal with often.
|
||||
//
|
||||
// OID for "IP=" IP address attributes, used with SKIP.
|
||||
public static final ObjectIdentifier ipAddress_oid =
|
||||
ObjectIdentifier.newInternal(ipAddress_data);
|
||||
|
||||
/*
|
||||
* OIDs from other sources which show up in X.500 names we
|
||||
* expect to deal with often
|
||||
*/
|
||||
/** OID for "IP=" IP address attributes, used with SKIP. */
|
||||
ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data));
|
||||
// Domain component OID from RFC 1274, RFC 2247, RFC 5280.
|
||||
//
|
||||
// OID for "DC=" domain component attributes, used with DNSNames in DN
|
||||
// format.
|
||||
public static final ObjectIdentifier DOMAIN_COMPONENT_OID =
|
||||
ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA);
|
||||
|
||||
/*
|
||||
* Domain component OID from RFC 1274, RFC 2247, RFC 5280
|
||||
*/
|
||||
|
||||
/*
|
||||
* OID for "DC=" domain component attributes, used with DNSNames in DN
|
||||
* format
|
||||
*/
|
||||
DOMAIN_COMPONENT_OID =
|
||||
intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA));
|
||||
|
||||
/** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
|
||||
userid_oid = intern(ObjectIdentifier.newInternal(userid_data));
|
||||
}
|
||||
// OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798.
|
||||
public static final ObjectIdentifier userid_oid =
|
||||
ObjectIdentifier.newInternal(userid_data);
|
||||
|
||||
/**
|
||||
* Return constraint type:<ul>
|
||||
|
||||
@ -87,7 +87,9 @@ final class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocket
|
||||
fd1 = new FileDescriptor();
|
||||
try {
|
||||
super.create();
|
||||
SocketCleanable.register(fd1);
|
||||
// make SocketCleanable treat fd1 as a stream socket
|
||||
// to avoid touching the counter in ResourceManager
|
||||
SocketCleanable.register(fd1, true);
|
||||
} catch (SocketException e) {
|
||||
fd1 = null;
|
||||
throw e;
|
||||
@ -114,8 +116,10 @@ final class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocket
|
||||
|
||||
bind0(lport, laddr, exclusiveBind);
|
||||
|
||||
SocketCleanable.register(fd);
|
||||
SocketCleanable.register(fd1);
|
||||
SocketCleanable.register(fd, false);
|
||||
// make SocketCleanable treat fd1 as a stream socket
|
||||
// to avoid touching the counter in ResourceManager
|
||||
SocketCleanable.register(fd1, true);
|
||||
}
|
||||
|
||||
protected synchronized void receive(DatagramPacket p)
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
|
||||
package java.awt.color;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -1017,42 +1018,25 @@ public class ICC_Profile implements Serializable {
|
||||
|
||||
|
||||
static byte[] getProfileDataFromStream(InputStream s) throws IOException {
|
||||
byte[] profileData;
|
||||
int profileSize;
|
||||
|
||||
byte[] header = new byte[128];
|
||||
int bytestoread = 128;
|
||||
int bytesread = 0;
|
||||
int n;
|
||||
BufferedInputStream bis = new BufferedInputStream(s);
|
||||
bis.mark(128);
|
||||
|
||||
while (bytestoread != 0) {
|
||||
if ((n = s.read(header, bytesread, bytestoread)) < 0) {
|
||||
return null;
|
||||
}
|
||||
bytesread += n;
|
||||
bytestoread -= n;
|
||||
}
|
||||
byte[] header = bis.readNBytes(128);
|
||||
if (header[36] != 0x61 || header[37] != 0x63 ||
|
||||
header[38] != 0x73 || header[39] != 0x70) {
|
||||
return null; /* not a valid profile */
|
||||
}
|
||||
profileSize = ((header[0] & 0xff) << 24) |
|
||||
((header[1] & 0xff) << 16) |
|
||||
((header[2] & 0xff) << 8) |
|
||||
(header[3] & 0xff);
|
||||
profileData = new byte[profileSize];
|
||||
System.arraycopy(header, 0, profileData, 0, 128);
|
||||
bytestoread = profileSize - 128;
|
||||
bytesread = 128;
|
||||
while (bytestoread != 0) {
|
||||
if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
|
||||
return null;
|
||||
}
|
||||
bytesread += n;
|
||||
bytestoread -= n;
|
||||
int profileSize = ((header[0] & 0xff) << 24) |
|
||||
((header[1] & 0xff) << 16) |
|
||||
((header[2] & 0xff) << 8) |
|
||||
(header[3] & 0xff);
|
||||
bis.reset();
|
||||
try {
|
||||
return bis.readNBytes(profileSize);
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new IOException("Color profile is too big");
|
||||
}
|
||||
|
||||
return profileData;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -1032,18 +1032,8 @@ public class BeanContextSupport extends BeanContextChildSupport
|
||||
int count = serializable;
|
||||
|
||||
while (count-- > 0) {
|
||||
Object child = null;
|
||||
BeanContextSupport.BCSChild bscc = null;
|
||||
|
||||
try {
|
||||
child = ois.readObject();
|
||||
bscc = (BeanContextSupport.BCSChild)ois.readObject();
|
||||
} catch (IOException ioe) {
|
||||
continue;
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object child = ois.readObject();
|
||||
BCSChild bscc = (BCSChild) ois.readObject();
|
||||
|
||||
synchronized(child) {
|
||||
BeanContextChild bcc = null;
|
||||
|
||||
@ -74,6 +74,7 @@ static void X11SD_SwapBytes(X11SDOps *xsdo, XImage *img, int depth, int bpp);
|
||||
static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
|
||||
SurfaceDataBounds *bounds,
|
||||
jint lockFlags);
|
||||
static int X11SD_GetBitmapPad(int pixelStride);
|
||||
|
||||
extern jfieldID validID;
|
||||
|
||||
@ -390,11 +391,33 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width
|
||||
xsdo->drawable = drawable;
|
||||
xsdo->isPixmap = JNI_FALSE;
|
||||
} else {
|
||||
jboolean sizeIsInvalid = JNI_FALSE;
|
||||
jlong scan = 0;
|
||||
|
||||
/*
|
||||
* width , height must be nonzero otherwise XCreatePixmap
|
||||
* generates BadValue in error_handler
|
||||
*/
|
||||
if (width <= 0 || height <= 0 || width > 32767 || height > 32767) {
|
||||
sizeIsInvalid = JNI_TRUE;
|
||||
} else {
|
||||
XImage* tmpImg = NULL;
|
||||
|
||||
AWT_LOCK();
|
||||
tmpImg = XCreateImage(awt_display,
|
||||
xsdo->configData->awt_visInfo.visual,
|
||||
depth, ZPixmap, 0, NULL, width, height,
|
||||
X11SD_GetBitmapPad(xsdo->configData->pixelStride), 0);
|
||||
if (tmpImg) {
|
||||
scan = (jlong) tmpImg->bytes_per_line;
|
||||
XDestroyImage(tmpImg);
|
||||
tmpImg = NULL;
|
||||
}
|
||||
AWT_UNLOCK();
|
||||
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
|
||||
}
|
||||
|
||||
if (sizeIsInvalid || (scan * height > 0x7FFFFFFFL)) {
|
||||
JNU_ThrowOutOfMemoryError(env,
|
||||
"Can't create offscreen surface");
|
||||
return JNI_FALSE;
|
||||
@ -405,7 +428,7 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width
|
||||
xsdo->pmHeight = height;
|
||||
|
||||
#ifdef MITSHM
|
||||
xsdo->shmPMData.pmSize = width * height * depth;
|
||||
xsdo->shmPMData.pmSize = (jlong) width * height * depth;
|
||||
xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
|
||||
if (forceSharedPixmaps) {
|
||||
AWT_LOCK();
|
||||
@ -508,7 +531,7 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo,
|
||||
return NULL;
|
||||
}
|
||||
shminfo->shmid =
|
||||
shmget(IPC_PRIVATE, height * img->bytes_per_line,
|
||||
shmget(IPC_PRIVATE, (size_t) height * img->bytes_per_line,
|
||||
IPC_CREAT|mitShmPermissionMask);
|
||||
if (shminfo->shmid < 0) {
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR,
|
||||
@ -570,7 +593,7 @@ XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height,
|
||||
XSync(awt_display, False);
|
||||
retImage = cachedXImage;
|
||||
cachedXImage = (XImage *)NULL;
|
||||
} else if (width * height * xsdo->depth > 0x10000) {
|
||||
} else if ((jlong) width * height * xsdo->depth > 0x10000) {
|
||||
retImage = X11SD_CreateSharedImage(xsdo, width, height);
|
||||
}
|
||||
return retImage;
|
||||
@ -870,7 +893,7 @@ static void X11SD_GetRasInfo(JNIEnv *env,
|
||||
int scan = xpriv->img->bytes_per_line;
|
||||
xpriv->x = x;
|
||||
xpriv->y = y;
|
||||
pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan;
|
||||
pRasInfo->rasBase = xpriv->img->data - x * mult - (intptr_t) y * scan;
|
||||
pRasInfo->pixelStride = mult;
|
||||
pRasInfo->pixelBitOffset = 0;
|
||||
pRasInfo->scanStride = scan;
|
||||
@ -1029,8 +1052,8 @@ X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds, X11SDOps *xsdo)
|
||||
|
||||
static void
|
||||
X11SD_SwapBytes(X11SDOps *xsdo, XImage * img, int depth, int bpp) {
|
||||
int lengthInBytes = img->height * img->bytes_per_line;
|
||||
int i;
|
||||
jlong lengthInBytes = (jlong) img->height * img->bytes_per_line;
|
||||
jlong i;
|
||||
|
||||
switch (depth) {
|
||||
case 12:
|
||||
@ -1103,7 +1126,7 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
|
||||
Drawable drawable;
|
||||
int depth = xsdo->depth;
|
||||
int mult = xsdo->configData->pixelStride;
|
||||
int pad = (mult == 3) ? 32 : mult * 8; // pad must be 8, 16, or 32
|
||||
int pad = X11SD_GetBitmapPad(mult);
|
||||
jboolean readBits = lockFlags & SD_LOCK_NEED_PIXELS;
|
||||
|
||||
x = bounds->x1;
|
||||
@ -1169,7 +1192,7 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
|
||||
}
|
||||
|
||||
scan = img->bytes_per_line;
|
||||
img->data = malloc(h * scan);
|
||||
img->data = malloc((size_t) h * scan);
|
||||
if (img->data == NULL) {
|
||||
XFree(img);
|
||||
return NULL;
|
||||
@ -1204,7 +1227,7 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
|
||||
int i;
|
||||
|
||||
img_addr = img->data +
|
||||
(temp.y1 - y) * scan + (temp.x1 - x) * mult;
|
||||
(intptr_t) (temp.y1 - y) * scan + (temp.x1 - x) * mult;
|
||||
temp_scan = temp_image->bytes_per_line;
|
||||
temp_addr = temp_image->data;
|
||||
bytes_to_copy = (temp.x2 - temp.x1) * mult;
|
||||
@ -1238,7 +1261,7 @@ static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
img->data = malloc(h * img->bytes_per_line);
|
||||
img->data = malloc((size_t) h * img->bytes_per_line);
|
||||
if (img->data == NULL) {
|
||||
XFree(img);
|
||||
return NULL;
|
||||
@ -1379,6 +1402,11 @@ X11SD_ReleasePixmapWithBg(JNIEnv *env, X11SDOps *xsdo)
|
||||
#endif /* MITSHM */
|
||||
}
|
||||
|
||||
static int X11SD_GetBitmapPad(int pixelStride) {
|
||||
// pad must be 8, 16, or 32
|
||||
return (pixelStride == 3) ? 32 : pixelStride * 8;
|
||||
}
|
||||
|
||||
#endif /* !HEADLESS */
|
||||
|
||||
/*
|
||||
|
||||
@ -79,7 +79,7 @@ typedef struct {
|
||||
XShmSegmentInfo *shmSegInfo; /* Shared Memory Segment Info */
|
||||
jint bytesPerLine; /* needed for ShMem lock */
|
||||
jboolean xRequestSent; /* true if x request is sent w/o XSync */
|
||||
jint pmSize;
|
||||
jlong pmSize;
|
||||
|
||||
jboolean usingShmPixmap;
|
||||
Drawable pixmap;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -29,6 +29,7 @@ import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.UnexpectedException;
|
||||
import java.rmi.activation.Activatable;
|
||||
import java.util.Map;
|
||||
@ -206,6 +207,13 @@ public class RemoteObjectInvocationHandler
|
||||
throw new IllegalArgumentException(
|
||||
"proxy not Remote instance");
|
||||
}
|
||||
|
||||
// Verify that the method is declared on an interface that extends Remote
|
||||
Class<?> decl = method.getDeclaringClass();
|
||||
if (!Remote.class.isAssignableFrom(decl)) {
|
||||
throw new RemoteException("Method is not Remote: " + decl + "::" + method);
|
||||
}
|
||||
|
||||
return ref.invoke((Remote) proxy, method, args,
|
||||
getMethodHash(method));
|
||||
} catch (Exception e) {
|
||||
|
||||
@ -27,7 +27,9 @@
|
||||
package sun.rmi.registry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.rmi.transport.StreamRemoteCall;
|
||||
|
||||
/**
|
||||
@ -83,8 +85,9 @@ public final class RegistryImpl_Skel
|
||||
java.lang.String $param_String_1;
|
||||
java.rmi.Remote $param_Remote_2;
|
||||
try {
|
||||
java.io.ObjectInput in = call.getInputStream();
|
||||
$param_String_1 = (java.lang.String) in.readObject();
|
||||
ObjectInputStream in = (ObjectInputStream)call.getInputStream();
|
||||
$param_String_1 =
|
||||
SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
|
||||
$param_Remote_2 = (java.rmi.Remote) in.readObject();
|
||||
} catch (ClassCastException | IOException | ClassNotFoundException e) {
|
||||
call.discardPendingRefs();
|
||||
@ -118,9 +121,10 @@ public final class RegistryImpl_Skel
|
||||
{
|
||||
java.lang.String $param_String_1;
|
||||
try {
|
||||
java.io.ObjectInput in = call.getInputStream();
|
||||
$param_String_1 = (java.lang.String) in.readObject();
|
||||
} catch (ClassCastException | IOException | ClassNotFoundException e) {
|
||||
ObjectInputStream in = (ObjectInputStream)call.getInputStream();
|
||||
$param_String_1 =
|
||||
SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
|
||||
} catch (ClassCastException | IOException e) {
|
||||
call.discardPendingRefs();
|
||||
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
|
||||
} finally {
|
||||
@ -144,8 +148,9 @@ public final class RegistryImpl_Skel
|
||||
java.lang.String $param_String_1;
|
||||
java.rmi.Remote $param_Remote_2;
|
||||
try {
|
||||
java.io.ObjectInput in = call.getInputStream();
|
||||
$param_String_1 = (java.lang.String) in.readObject();
|
||||
ObjectInputStream in = (ObjectInputStream)call.getInputStream();
|
||||
$param_String_1 =
|
||||
SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
|
||||
$param_Remote_2 = (java.rmi.Remote) in.readObject();
|
||||
} catch (ClassCastException | IOException | java.lang.ClassNotFoundException e) {
|
||||
call.discardPendingRefs();
|
||||
@ -169,9 +174,10 @@ public final class RegistryImpl_Skel
|
||||
|
||||
java.lang.String $param_String_1;
|
||||
try {
|
||||
java.io.ObjectInput in = call.getInputStream();
|
||||
$param_String_1 = (java.lang.String) in.readObject();
|
||||
} catch (ClassCastException | IOException | ClassNotFoundException e) {
|
||||
ObjectInputStream in = (ObjectInputStream)call.getInputStream();
|
||||
$param_String_1 =
|
||||
SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
|
||||
} catch (ClassCastException | IOException e) {
|
||||
call.discardPendingRefs();
|
||||
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
|
||||
} finally {
|
||||
|
||||
@ -27,6 +27,7 @@ package sun.rmi.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.MarshalException;
|
||||
@ -39,6 +40,8 @@ import java.rmi.server.RemoteObject;
|
||||
import java.rmi.server.RemoteRef;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.rmi.runtime.Log;
|
||||
import sun.rmi.transport.Connection;
|
||||
import sun.rmi.transport.LiveRef;
|
||||
@ -318,6 +321,8 @@ public class UnicastRef implements RemoteRef {
|
||||
} else {
|
||||
throw new Error("Unrecognized primitive type: " + type);
|
||||
}
|
||||
} else if (type == String.class && in instanceof ObjectInputStream) {
|
||||
return SharedSecrets.getJavaObjectInputStreamReadString().readString((ObjectInputStream)in);
|
||||
} else {
|
||||
return in.readObject();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -29,6 +29,7 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
@ -553,6 +554,9 @@ public class TCPEndpoint implements Endpoint {
|
||||
host = in.readUTF();
|
||||
port = in.readInt();
|
||||
csf = (RMIClientSocketFactory) in.readObject();
|
||||
if (Proxy.isProxyClass(csf.getClass())) {
|
||||
throw new IOException("Invalid SocketFactory");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -73,6 +73,7 @@ public class Checksum {
|
||||
// draft-brezak-win2k-krb-rc4-hmac-04.txt
|
||||
public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;
|
||||
|
||||
// default checksum type, -1 if not set
|
||||
static int CKSUMTYPE_DEFAULT;
|
||||
static int SAFECKSUMTYPE_DEFAULT;
|
||||
|
||||
@ -87,26 +88,19 @@ public class Checksum {
|
||||
try {
|
||||
cfg = Config.getInstance();
|
||||
temp = cfg.get("libdefaults", "default_checksum");
|
||||
if (temp != null)
|
||||
{
|
||||
CKSUMTYPE_DEFAULT = Config.getType(temp);
|
||||
} else {
|
||||
/*
|
||||
* If the default checksum is not
|
||||
* specified in the configuration we
|
||||
* set it to RSA_MD5. We follow the MIT and
|
||||
* SEAM implementation.
|
||||
*/
|
||||
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
if (temp != null) {
|
||||
CKSUMTYPE_DEFAULT = Config.getType(temp);
|
||||
} else {
|
||||
CKSUMTYPE_DEFAULT = -1;
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Exception in getting default checksum "+
|
||||
"value from the configuration. " +
|
||||
"Setting default checksum to be RSA-MD5");
|
||||
"No default checksum set.");
|
||||
exc.printStackTrace();
|
||||
}
|
||||
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
|
||||
CKSUMTYPE_DEFAULT = -1;
|
||||
}
|
||||
|
||||
|
||||
@ -116,117 +110,100 @@ public class Checksum {
|
||||
{
|
||||
SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
|
||||
} else {
|
||||
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
|
||||
SAFECKSUMTYPE_DEFAULT = -1;
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Exception in getting safe default " +
|
||||
"checksum value " +
|
||||
"from the configuration. Setting " +
|
||||
"safe default checksum to be RSA-MD5");
|
||||
"from the configuration Setting. " +
|
||||
"No safe default checksum set.");
|
||||
exc.printStackTrace();
|
||||
}
|
||||
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
|
||||
SAFECKSUMTYPE_DEFAULT = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Checksum using the raw data and type.
|
||||
*
|
||||
* This constructor is only used by Authenticator Checksum
|
||||
* {@link sun.security.jgss.krb5.InitialToken.OverloadedChecksum}
|
||||
* where the checksum type must be 0x8003
|
||||
* (see https://tools.ietf.org/html/rfc4121#section-4.1.1)
|
||||
* and checksum field/value is used to convey service flags,
|
||||
* channel bindings, and optional delegation information.
|
||||
* This special type does NOT have a {@link CksumType} and has its
|
||||
* own calculating and verification rules. It does has the same
|
||||
* ASN.1 encoding though.
|
||||
*
|
||||
* @param data the byte array of checksum.
|
||||
* @param new_cksumType the type of checksum.
|
||||
*
|
||||
*/
|
||||
// used in InitialToken
|
||||
public Checksum(byte[] data, int new_cksumType) {
|
||||
cksumType = new_cksumType;
|
||||
checksum = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Checksum by calculating the checksum over the data
|
||||
* using specified checksum type.
|
||||
* @param new_cksumType the type of checksum.
|
||||
* @param data the data that needs to be performed a checksum calculation on.
|
||||
* Constructs a new Checksum by calculating over the data using
|
||||
* the specified checksum type. If the checksum is unkeyed, key
|
||||
* and usage are ignored.
|
||||
*
|
||||
* @param new_cksumType the type of checksum. If set to -1, the
|
||||
* {@linkplain EType#checksumType() mandatory checksum type}
|
||||
* for the encryption type of {@code key} will be used
|
||||
* @param data the data that needs to be performed a checksum calculation on
|
||||
* @param key the key used by a keyed checksum
|
||||
* @param usage the usage used by a keyed checksum
|
||||
*/
|
||||
public Checksum(int new_cksumType, byte[] data)
|
||||
throws KdcErrException, KrbCryptoException {
|
||||
|
||||
cksumType = new_cksumType;
|
||||
CksumType cksumEngine = CksumType.getInstance(cksumType);
|
||||
if (!cksumEngine.isSafe()) {
|
||||
checksum = cksumEngine.calculateChecksum(data, data.length);
|
||||
} else {
|
||||
throw new KdcErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Checksum by calculating the keyed checksum
|
||||
* over the data using specified checksum type.
|
||||
* @param new_cksumType the type of checksum.
|
||||
* @param data the data that needs to be performed a checksum calculation on.
|
||||
*/
|
||||
// KrbSafe, KrbTgsReq
|
||||
public Checksum(int new_cksumType, byte[] data,
|
||||
EncryptionKey key, int usage)
|
||||
throws KdcErrException, KrbApErrException, KrbCryptoException {
|
||||
cksumType = new_cksumType;
|
||||
CksumType cksumEngine = CksumType.getInstance(cksumType);
|
||||
if (!cksumEngine.isSafe())
|
||||
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
|
||||
checksum =
|
||||
cksumEngine.calculateKeyedChecksum(data,
|
||||
data.length,
|
||||
key.getBytes(),
|
||||
usage);
|
||||
EncryptionKey key, int usage)
|
||||
throws KdcErrException, KrbApErrException, KrbCryptoException {
|
||||
if (new_cksumType == -1) {
|
||||
cksumType = EType.getInstance(key.getEType()).checksumType();
|
||||
} else {
|
||||
cksumType = new_cksumType;
|
||||
}
|
||||
checksum = CksumType.getInstance(cksumType).calculateChecksum(
|
||||
data, data.length, key.getBytes(), usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the keyed checksum over the data passed in.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key,
|
||||
int usage)
|
||||
throws KdcErrException, KrbApErrException, KrbCryptoException {
|
||||
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key, int usage)
|
||||
throws KdcErrException, KrbApErrException, KrbCryptoException {
|
||||
CksumType cksumEngine = CksumType.getInstance(cksumType);
|
||||
if (!cksumEngine.isSafe())
|
||||
if (!cksumEngine.isKeyed()) {
|
||||
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
|
||||
return cksumEngine.verifyKeyedChecksum(data,
|
||||
data.length,
|
||||
key.getBytes(),
|
||||
checksum,
|
||||
usage);
|
||||
}
|
||||
|
||||
// =============== ATTENTION! Use with care ==================
|
||||
// According to https://tools.ietf.org/html/rfc3961#section-6.1,
|
||||
// An unkeyed checksum should only be used "in limited circumstances
|
||||
// where the lack of a key does not provide a window for an attack,
|
||||
// preferably as part of an encrypted message".
|
||||
public boolean verifyAnyChecksum(byte[] data, EncryptionKey key,
|
||||
int usage)
|
||||
throws KdcErrException, KrbCryptoException {
|
||||
CksumType cksumEngine = CksumType.getInstance(cksumType);
|
||||
if (!cksumEngine.isSafe()) {
|
||||
return cksumEngine.verifyChecksum(data, checksum);
|
||||
} else {
|
||||
return cksumEngine.verifyKeyedChecksum(data,
|
||||
data.length,
|
||||
key.getBytes(),
|
||||
checksum,
|
||||
usage);
|
||||
return cksumEngine.verifyChecksum(
|
||||
data, data.length, key.getBytes(), checksum, usage);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
|
||||
this(Checksum.CKSUMTYPE_DEFAULT, data);
|
||||
|
||||
/**
|
||||
* Verifies the checksum over the data passed in. The checksum might
|
||||
* be a keyed or not.
|
||||
*
|
||||
* =============== ATTENTION! Use with care ==================
|
||||
* According to https://tools.ietf.org/html/rfc3961#section-6.1,
|
||||
* An unkeyed checksum should only be used "in limited circumstances
|
||||
* where the lack of a key does not provide a window for an attack,
|
||||
* preferably as part of an encrypted message".
|
||||
*/
|
||||
public boolean verifyAnyChecksum(byte[] data, EncryptionKey key, int usage)
|
||||
throws KdcErrException, KrbCryptoException {
|
||||
return CksumType.getInstance(cksumType).verifyChecksum(
|
||||
data, data.length, key.getBytes(), checksum, usage);
|
||||
}
|
||||
*/
|
||||
|
||||
boolean isEqual(Checksum cksum) throws KdcErrException {
|
||||
if (cksumType != cksum.cksumType)
|
||||
if (cksumType != cksum.cksumType) {
|
||||
return false;
|
||||
CksumType cksumEngine = CksumType.getInstance(cksumType);
|
||||
}
|
||||
return CksumType.isChecksumEqual(checksum, cksum.checksum);
|
||||
}
|
||||
|
||||
|
||||
@ -318,28 +318,8 @@ public class KrbTgsReq {
|
||||
byte[] temp = reqBody.asn1Encode(Krb5.KRB_TGS_REQ);
|
||||
// if the checksum type is one of the keyed checksum types,
|
||||
// use session key.
|
||||
Checksum cksum;
|
||||
switch (Checksum.CKSUMTYPE_DEFAULT) {
|
||||
case Checksum.CKSUMTYPE_RSA_MD4_DES:
|
||||
case Checksum.CKSUMTYPE_DES_MAC:
|
||||
case Checksum.CKSUMTYPE_DES_MAC_K:
|
||||
case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
|
||||
case Checksum.CKSUMTYPE_RSA_MD5_DES:
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
|
||||
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128:
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256:
|
||||
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
|
||||
Checksum cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
|
||||
KeyUsage.KU_PA_TGS_REQ_CKSUM);
|
||||
break;
|
||||
case Checksum.CKSUMTYPE_CRC32:
|
||||
case Checksum.CKSUMTYPE_RSA_MD4:
|
||||
case Checksum.CKSUMTYPE_RSA_MD5:
|
||||
default:
|
||||
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp);
|
||||
}
|
||||
|
||||
// Usage will be KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -102,7 +102,7 @@ class TCPClient extends NetClient {
|
||||
}
|
||||
|
||||
try {
|
||||
return IOUtils.readFully(in, len, true);
|
||||
return IOUtils.readExactlyNBytes(in, len);
|
||||
} catch (IOException ioe) {
|
||||
if (Krb5.DEBUG) {
|
||||
System.out.println(
|
||||
|
||||
@ -135,6 +135,7 @@ public class PAForUserEnc {
|
||||
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), name.getRealm().asn1Encode());
|
||||
|
||||
try {
|
||||
// MS-SFU 2.2.1: use hmac-md5 checksum regardless of key type
|
||||
Checksum cks = new Checksum(
|
||||
Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR,
|
||||
getS4UByteArray(),
|
||||
|
||||
@ -128,7 +128,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
|
||||
length--;
|
||||
for (int i = 0; i <= length; i++) {
|
||||
namelength = readLength4();
|
||||
byte[] bytes = IOUtils.readFully(this, namelength, true);
|
||||
byte[] bytes = IOUtils.readExactlyNBytes(this, namelength);
|
||||
result.add(new String(bytes));
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
@ -186,7 +186,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
|
||||
if (version == KRB5_FCC_FVNO_3)
|
||||
read(2); /* keytype recorded twice in fvno 3 */
|
||||
keyLen = readLength4();
|
||||
byte[] bytes = IOUtils.readFully(this, keyLen, true);
|
||||
byte[] bytes = IOUtils.readExactlyNBytes(this, keyLen);
|
||||
return new EncryptionKey(bytes, keyType, version);
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
|
||||
for (int i = 0; i < num; i++) {
|
||||
adtype = read(2);
|
||||
adlength = readLength4();
|
||||
data = IOUtils.readFully(this, adlength, true);
|
||||
data = IOUtils.readExactlyNBytes(this, adlength);
|
||||
auData.add(new AuthorizationDataEntry(adtype, data));
|
||||
}
|
||||
return auData.toArray(new AuthorizationDataEntry[auData.size()]);
|
||||
@ -253,7 +253,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
|
||||
if (length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return IOUtils.readFully(this, length, true);
|
||||
return IOUtils.readExactlyNBytes(this, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -31,10 +31,7 @@
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Config;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.KrbException;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
@ -81,12 +78,25 @@ public abstract class CksumType {
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha1Aes128CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
|
||||
cksumType = new HmacSha1Aes256CksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha1Aes256CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128:
|
||||
cksumType = new HmacSha2Aes128CksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha2Aes128CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256:
|
||||
cksumType = new HmacSha2Aes256CksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha2Aes256CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
|
||||
cksumType = new HmacMd5ArcFourCksumType();
|
||||
cksumTypeName =
|
||||
@ -117,32 +127,11 @@ public abstract class CksumType {
|
||||
return cksumType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns default checksum type.
|
||||
*/
|
||||
public static CksumType getInstance() throws KdcErrException {
|
||||
// this method provided for Kerberos applications.
|
||||
int cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
|
||||
try {
|
||||
Config c = Config.getInstance();
|
||||
if ((cksumType = (Config.getType(c.get("libdefaults",
|
||||
"ap_req_checksum_type")))) == - 1) {
|
||||
if ((cksumType = Config.getType(c.get("libdefaults",
|
||||
"checksum_type"))) == -1) {
|
||||
cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
|
||||
}
|
||||
}
|
||||
} catch (KrbException e) {
|
||||
}
|
||||
return getInstance(cksumType);
|
||||
}
|
||||
|
||||
public abstract int confounderSize();
|
||||
|
||||
public abstract int cksumType();
|
||||
|
||||
public abstract boolean isSafe();
|
||||
public abstract boolean isKeyed();
|
||||
|
||||
public abstract int cksumSize();
|
||||
|
||||
@ -150,18 +139,12 @@ public abstract class CksumType {
|
||||
|
||||
public abstract int keySize();
|
||||
|
||||
public abstract byte[] calculateChecksum(byte[] data, int size)
|
||||
throws KrbCryptoException;
|
||||
|
||||
public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
|
||||
// Note: key and usage will be ignored for an unkeyed checksum.
|
||||
public abstract byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) throws KrbCryptoException;
|
||||
|
||||
public boolean verifyChecksum(byte[] data, byte[] checksum)
|
||||
throws KrbCryptoException {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
public abstract boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
// Note: key and usage will be ignored for an unkeyed checksum.
|
||||
public abstract boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
|
||||
|
||||
public static boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
|
||||
|
||||
@ -32,7 +32,6 @@ package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.*;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
public class Crc32CksumType extends CksumType {
|
||||
|
||||
@ -47,7 +46,7 @@ public class Crc32CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_CRC32;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -63,18 +62,15 @@ public class Crc32CksumType extends CksumType {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
public byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) {
|
||||
return crc32.byte2crc32sum_bytes(data, size);
|
||||
}
|
||||
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) {
|
||||
return false;
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) {
|
||||
return CksumType.isChecksumEqual(checksum,
|
||||
crc32.byte2crc32sum_bytes(data));
|
||||
}
|
||||
|
||||
public static byte[] int2quad(long input) {
|
||||
|
||||
@ -53,7 +53,7 @@ public class DesCbcCrcEType extends DesCbcEType {
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_CRC32;
|
||||
return Checksum.CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
|
||||
@ -49,7 +49,7 @@ public class DesMacCksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_DES_MAC;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -65,10 +65,6 @@ public class DesMacCksumType extends CksumType {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -78,7 +74,7 @@ public class DesMacCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
byte[] conf = Confounder.bytes(confounderSize());
|
||||
@ -130,7 +126,7 @@ public class DesMacCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
byte[] cksum = decryptKeyedChecksum(checksum, key);
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ public class DesMacKCksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_DES_MAC_K;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -64,10 +64,6 @@ public class DesMacKCksumType extends CksumType {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -77,7 +73,7 @@ public class DesMacKCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
//check for weak keys
|
||||
try {
|
||||
@ -93,9 +89,9 @@ public class DesMacKCksumType extends CksumType {
|
||||
return cksum;
|
||||
}
|
||||
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
byte[] new_cksum = calculateKeyedChecksum(data, data.length, key, usage);
|
||||
byte[] new_cksum = calculateChecksum(data, data.length, key, usage);
|
||||
return isChecksumEqual(checksum, new_cksum);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -28,8 +28,6 @@ package sun.security.krb5.internal.crypto;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
@ -51,7 +49,7 @@ public class HmacMd5ArcFourCksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -67,10 +65,6 @@ public class HmacMd5ArcFourCksumType extends CksumType {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -78,7 +72,7 @@ public class HmacMd5ArcFourCksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -98,7 +92,7 @@ public class HmacMd5ArcFourCksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 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
|
||||
@ -28,8 +28,6 @@ package sun.security.krb5.internal.crypto;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/*
|
||||
@ -51,7 +49,7 @@ public class HmacSha1Aes128CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -67,10 +65,6 @@ public class HmacSha1Aes128CksumType extends CksumType {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -78,7 +72,7 @@ public class HmacSha1Aes128CksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -98,7 +92,7 @@ public class HmacSha1Aes128CksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 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
|
||||
@ -28,8 +28,6 @@ package sun.security.krb5.internal.crypto;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/*
|
||||
@ -51,7 +49,7 @@ public class HmacSha1Aes256CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -67,10 +65,6 @@ public class HmacSha1Aes256CksumType extends CksumType {
|
||||
return 32; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -78,7 +72,7 @@ public class HmacSha1Aes256CksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -98,7 +92,7 @@ public class HmacSha1Aes256CksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 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
|
||||
@ -28,8 +28,6 @@ package sun.security.krb5.internal.crypto;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
@ -45,7 +43,7 @@ public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -61,10 +59,6 @@ public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
return 24; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -72,7 +66,7 @@ public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -92,7 +86,7 @@ public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -47,7 +47,7 @@ public class HmacSha2Aes128CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -63,10 +63,6 @@ public class HmacSha2Aes128CksumType extends CksumType {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -74,7 +70,7 @@ public class HmacSha2Aes128CksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -94,7 +90,7 @@ public class HmacSha2Aes128CksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -47,7 +47,7 @@ public class HmacSha2Aes256CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -63,10 +63,6 @@ public class HmacSha2Aes256CksumType extends CksumType {
|
||||
return 32; // bytes
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
@ -74,7 +70,7 @@ public class HmacSha2Aes256CksumType extends CksumType {
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
@ -94,7 +90,7 @@ public class HmacSha2Aes256CksumType extends CksumType {
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
|
||||
@ -33,8 +33,6 @@ import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
|
||||
public final class RsaMd5CksumType extends CksumType {
|
||||
|
||||
@ -49,7 +47,7 @@ public final class RsaMd5CksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -74,7 +72,8 @@ public final class RsaMd5CksumType extends CksumType {
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size) throws KrbCryptoException{
|
||||
public byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) throws KrbCryptoException{
|
||||
MessageDigest md5;
|
||||
byte[] result = null;
|
||||
try {
|
||||
@ -91,18 +90,9 @@ public final class RsaMd5CksumType extends CksumType {
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) throws KrbCryptoException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyChecksum(byte[] data, byte[] checksum)
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
|
||||
|
||||
@ -33,12 +33,8 @@ import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
public final class RsaMd5DesCksumType extends CksumType {
|
||||
@ -54,7 +50,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5_DES;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -79,7 +75,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
//prepend confounder
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
@ -88,7 +84,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
//calculate md5 cksum
|
||||
byte[] mdc_cksum = calculateChecksum(new_data, new_data.length);
|
||||
byte[] mdc_cksum = calculateRawChecksum(new_data, new_data.length);
|
||||
byte[] cksum = new byte[cksumSize()];
|
||||
System.arraycopy(conf, 0, cksum, 0, confounderSize());
|
||||
System.arraycopy(mdc_cksum, 0, cksum, confounderSize(),
|
||||
@ -125,7 +121,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public boolean verifyKeyedChecksum(byte[] data, int size,
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
//decrypt checksum
|
||||
byte[] cksum = decryptKeyedChecksum(checksum, key);
|
||||
@ -135,7 +131,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
System.arraycopy(cksum, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
byte[] new_cksum = calculateChecksum(new_data, new_data.length);
|
||||
byte[] new_cksum = calculateRawChecksum(new_data, new_data.length);
|
||||
//extract original cksum value
|
||||
byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
|
||||
System.arraycopy(cksum, confounderSize(), orig_cksum, 0,
|
||||
@ -181,7 +177,7 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size) throws KrbCryptoException{
|
||||
private byte[] calculateRawChecksum(byte[] data, int size) throws KrbCryptoException{
|
||||
MessageDigest md5;
|
||||
byte[] result = null;
|
||||
try {
|
||||
@ -197,5 +193,4 @@ public final class RsaMd5DesCksumType extends CksumType {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -132,8 +132,9 @@ seconds_until(int inputIsUTC, TimeStamp *time)
|
||||
return 0;
|
||||
}
|
||||
ULONGLONG diff = (time->QuadPart - uiLocal.QuadPart) / 10000000;
|
||||
if (diff > (ULONGLONG)~(OM_uint32)0)
|
||||
if (diff > (ULONGLONG)~(OM_uint32)0) {
|
||||
return GSS_C_INDEFINITE;
|
||||
}
|
||||
return (OM_uint32)diff;
|
||||
}
|
||||
|
||||
@ -177,8 +178,10 @@ static gss_cred_id_t
|
||||
new_cred()
|
||||
{
|
||||
gss_cred_id_t out = new gss_cred_id_struct;
|
||||
out->phCredK = out->phCredS = NULL;
|
||||
out->time = 0L;
|
||||
if (out) {
|
||||
out->phCredK = out->phCredS = NULL;
|
||||
out->time = 0L;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -864,6 +867,7 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
SecBufferDesc outBuffDesc;
|
||||
SecBuffer outSecBuff;
|
||||
BOOLEAN isSPNEGO = is_same_oid(mech_type, &SPNEGO_OID);
|
||||
CredHandle* newCred = NULL;
|
||||
|
||||
gss_ctx_id_t pc;
|
||||
|
||||
@ -928,7 +932,10 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
pc->isLocalCred = FALSE;
|
||||
} else {
|
||||
PP("No credentials provided, acquire myself");
|
||||
CredHandle* newCred = new CredHandle;
|
||||
newCred = new CredHandle;
|
||||
if (!newCred) {
|
||||
goto err;
|
||||
}
|
||||
SEC_WINNT_AUTH_IDENTITY_EX auth;
|
||||
ZeroMemory(&auth, sizeof(auth));
|
||||
auth.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
|
||||
@ -947,7 +954,6 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
newCred,
|
||||
&lifeTime);
|
||||
if (!(SEC_SUCCESS(ss))) {
|
||||
delete newCred;
|
||||
goto err;
|
||||
}
|
||||
pc->phCred = newCred;
|
||||
@ -989,7 +995,6 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
output_token->value = new char[outSecBuff.cbBuffer];
|
||||
if (!output_token->value) {
|
||||
FreeContextBuffer(outSecBuff.pvBuffer);
|
||||
output_token->length = 0;
|
||||
goto err;
|
||||
}
|
||||
memcpy(output_token->value, outSecBuff.pvBuffer, outSecBuff.cbBuffer);
|
||||
@ -1009,14 +1014,17 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
err:
|
||||
if (newCred) {
|
||||
delete newCred;
|
||||
}
|
||||
if (firstTime) {
|
||||
OM_uint32 dummy;
|
||||
gss_delete_sec_context(&dummy, context_handle, GSS_C_NO_BUFFER);
|
||||
}
|
||||
if (output_token->value) {
|
||||
gss_release_buffer(NULL, output_token);
|
||||
output_token = GSS_C_NO_BUFFER;
|
||||
}
|
||||
output_token = GSS_C_NO_BUFFER;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
@ -1233,17 +1241,26 @@ gss_get_mic(OM_uint32 *minor_status,
|
||||
secBuff[1].cbBuffer = context_handle->SecPkgContextSizes.cbMaxSignature;
|
||||
secBuff[1].pvBuffer = msg_token->value = new char[secBuff[1].cbBuffer];
|
||||
|
||||
if (!secBuff[1].pvBuffer) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ss = MakeSignature((PCtxtHandle)&context_handle->hCtxt, 0, &buffDesc, 0);
|
||||
|
||||
if (!SEC_SUCCESS(ss)) {
|
||||
msg_token->length = 0;
|
||||
msg_token->value = NULL;
|
||||
delete[] secBuff[1].pvBuffer;
|
||||
return GSS_S_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
msg_token->length = secBuff[1].cbBuffer;
|
||||
return GSS_S_COMPLETE;
|
||||
|
||||
err:
|
||||
msg_token->length = 0;
|
||||
msg_token->value = NULL;
|
||||
if (secBuff[1].pvBuffer) {
|
||||
delete[] secBuff[1].pvBuffer;
|
||||
}
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) OM_uint32
|
||||
@ -1317,16 +1334,25 @@ gss_wrap(OM_uint32 *minor_status,
|
||||
context_handle->SecPkgContextSizes.cbSecurityTrailer
|
||||
+ input_message_buffer->length
|
||||
+ context_handle->SecPkgContextSizes.cbBlockSize);;
|
||||
if (!output_message_buffer->value) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
secBuff[1].BufferType = SECBUFFER_DATA;
|
||||
secBuff[1].cbBuffer = (ULONG)input_message_buffer->length;
|
||||
secBuff[1].pvBuffer = malloc(secBuff[1].cbBuffer);
|
||||
if (!secBuff[1].pvBuffer) {
|
||||
goto err;
|
||||
}
|
||||
memcpy_s(secBuff[1].pvBuffer, secBuff[1].cbBuffer,
|
||||
input_message_buffer->value, input_message_buffer->length);
|
||||
|
||||
secBuff[2].BufferType = SECBUFFER_PADDING;
|
||||
secBuff[2].cbBuffer = context_handle->SecPkgContextSizes.cbBlockSize;
|
||||
secBuff[2].pvBuffer = malloc(secBuff[2].cbBuffer);
|
||||
if (!secBuff[2].pvBuffer) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ss = EncryptMessage((PCtxtHandle)&context_handle->hCtxt,
|
||||
conf_req_flag ? 0 : SECQOP_WRAP_NO_ENCRYPT,
|
||||
@ -1336,12 +1362,7 @@ gss_wrap(OM_uint32 *minor_status,
|
||||
}
|
||||
|
||||
if (!SEC_SUCCESS(ss)) {
|
||||
free(secBuff[0].pvBuffer);
|
||||
free(secBuff[1].pvBuffer);
|
||||
free(secBuff[2].pvBuffer);
|
||||
output_message_buffer->length = 0;
|
||||
output_message_buffer->value = NULL;
|
||||
return GSS_S_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy_s((PBYTE)secBuff[0].pvBuffer + secBuff[0].cbBuffer,
|
||||
@ -1359,6 +1380,20 @@ gss_wrap(OM_uint32 *minor_status,
|
||||
free(secBuff[2].pvBuffer);
|
||||
|
||||
return GSS_S_COMPLETE;
|
||||
|
||||
err:
|
||||
if (secBuff[0].pvBuffer) {
|
||||
free(secBuff[0].pvBuffer);
|
||||
}
|
||||
if (secBuff[1].pvBuffer) {
|
||||
free(secBuff[1].pvBuffer);
|
||||
}
|
||||
if (secBuff[2].pvBuffer) {
|
||||
free(secBuff[2].pvBuffer);
|
||||
}
|
||||
output_message_buffer->length = 0;
|
||||
output_message_buffer->value = NULL;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) OM_uint32
|
||||
@ -1386,6 +1421,11 @@ gss_unwrap(OM_uint32 *minor_status,
|
||||
secBuff[0].BufferType = SECBUFFER_STREAM;
|
||||
secBuff[0].cbBuffer = (ULONG)input_message_buffer->length;
|
||||
secBuff[0].pvBuffer = malloc(input_message_buffer->length);
|
||||
|
||||
if (!secBuff[0].pvBuffer) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy_s(secBuff[0].pvBuffer, input_message_buffer->length,
|
||||
input_message_buffer->value, input_message_buffer->length);
|
||||
|
||||
@ -1398,21 +1438,31 @@ gss_unwrap(OM_uint32 *minor_status,
|
||||
*qop_state = ulQop;
|
||||
}
|
||||
if (!SEC_SUCCESS(ss)) {
|
||||
free(secBuff[0].pvBuffer);
|
||||
output_message_buffer->length = 0;
|
||||
output_message_buffer->value = NULL;
|
||||
return GSS_S_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Must allocate a new memory block so client can release it correctly
|
||||
output_message_buffer->length = secBuff[1].cbBuffer;
|
||||
output_message_buffer->value = new char[secBuff[1].cbBuffer];
|
||||
|
||||
if (!output_message_buffer->value) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy_s(output_message_buffer->value, secBuff[1].cbBuffer,
|
||||
secBuff[1].pvBuffer, secBuff[1].cbBuffer);
|
||||
*conf_state = ulQop == SECQOP_WRAP_NO_ENCRYPT ? 0 : 1;
|
||||
|
||||
free(secBuff[0].pvBuffer);
|
||||
return GSS_S_COMPLETE;
|
||||
|
||||
err:
|
||||
if (secBuff[0].pvBuffer) {
|
||||
free(secBuff[0].pvBuffer);
|
||||
}
|
||||
output_message_buffer->length = 0;
|
||||
output_message_buffer->value = NULL;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) OM_uint32
|
||||
@ -1544,11 +1594,19 @@ gss_display_status(OM_uint32 *minor_status,
|
||||
msg, 256, 0);
|
||||
if (len > 0) {
|
||||
status_string->value = new char[len + 20];
|
||||
if (!status_string->value) {
|
||||
status_string = GSS_C_NO_BUFFER;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
status_string->length = sprintf_s(
|
||||
(LPSTR)status_string->value, len + 19,
|
||||
"(%lx) %ls", status_value, msg);
|
||||
} else {
|
||||
status_string->value = new char[33];
|
||||
if (!status_string->value) {
|
||||
status_string = GSS_C_NO_BUFFER;
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
status_string->length = sprintf_s(
|
||||
(LPSTR)status_string->value, 32,
|
||||
"status is %lx", status_value);
|
||||
|
||||
@ -505,14 +505,15 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
/**
|
||||
* Attribute the given tree, mostly reverting side-effects applied to shared
|
||||
* compiler state. Exceptions include the ArgumentAttr.argumentTypeCache,
|
||||
* changes to which may be preserved if localCache is null.
|
||||
* changes to which may be preserved if localCache is null and errors reported
|
||||
* outside of the speculatively attributed tree.
|
||||
*/
|
||||
<Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo,
|
||||
Supplier<DiagnosticHandler> diagHandlerCreator, AttributionMode attributionMode,
|
||||
LocalCacheContext localCache) {
|
||||
Env<AttrContext> speculativeEnv = env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
|
||||
speculativeEnv.info.attributionMode = attributionMode;
|
||||
Log.DiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator != null ? diagHandlerCreator.get() : new DeferredDiagnosticHandler(log);
|
||||
Log.DiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator != null ? diagHandlerCreator.get() : new DeferredAttrDiagHandler(log, tree);
|
||||
DeferredCompletionFailureHandler.Handler prevCFHandler = dcfh.setHandler(dcfh.speculativeCodeHandler);
|
||||
Queues prevQueues = annotate.setQueues(new Queues());
|
||||
int nwarnings = log.nwarnings;
|
||||
@ -531,6 +532,35 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
//where
|
||||
static class DeferredAttrDiagHandler extends Log.DeferredDiagnosticHandler {
|
||||
|
||||
static class PosScanner extends TreeScanner {
|
||||
DiagnosticPosition pos;
|
||||
boolean found = false;
|
||||
|
||||
PosScanner(DiagnosticPosition pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scan(JCTree tree) {
|
||||
if (tree != null &&
|
||||
tree.pos() == pos) {
|
||||
found = true;
|
||||
}
|
||||
super.scan(tree);
|
||||
}
|
||||
}
|
||||
|
||||
DeferredAttrDiagHandler(Log log, JCTree newTree) {
|
||||
super(log, d -> {
|
||||
PosScanner posScanner = new PosScanner(d.getDiagnosticPosition());
|
||||
posScanner.scan(newTree);
|
||||
return posScanner.found;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A deferred context is created on each method check. A deferred context is
|
||||
|
||||
@ -733,6 +733,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
container.close();
|
||||
}
|
||||
containers.clear();
|
||||
pathsAndContainersByLocationAndRelativeDirectory.clear();
|
||||
nonIndexingContainersByLocation.clear();
|
||||
contentCache.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -92,6 +92,11 @@ abstract class AbstractLayout implements MemoryLayout {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSize() {
|
||||
return size.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long bitSize() {
|
||||
return size.orElseThrow(this::badSizeException);
|
||||
|
||||
@ -31,7 +31,7 @@ import jdk.internal.foreign.MemoryAddressImpl;
|
||||
/**
|
||||
* A memory address encodes an offset within a given {@link MemorySegment}. Memory addresses are typically obtained
|
||||
* using the {@link MemorySegment#baseAddress()} method; such addresses can then be adjusted as required,
|
||||
* using {@link MemoryAddress#offset(long)}.
|
||||
* using {@link MemoryAddress#addOffset(long)}.
|
||||
* <p>
|
||||
* A memory address is typically used as the first argument in a memory access var handle call, to perform some operation
|
||||
* on the underlying memory backing a given memory segment. Since a memory address is always associated with a memory segment,
|
||||
@ -53,11 +53,11 @@ import jdk.internal.foreign.MemoryAddressImpl;
|
||||
*/
|
||||
public interface MemoryAddress {
|
||||
/**
|
||||
* Creates a new memory address with given offset (in bytes) from current one.
|
||||
* @param l specified offset (in bytes), relative to this address, which should be used to create the new address.
|
||||
* Creates a new memory address with given offset (in bytes), which might be negative, from current one.
|
||||
* @param offset specified offset (in bytes), relative to this address, which should be used to create the new address.
|
||||
* @return a new memory address with given offset from current one.
|
||||
*/
|
||||
MemoryAddress offset(long l);
|
||||
MemoryAddress addOffset(long offset);
|
||||
|
||||
/**
|
||||
* The offset of this memory address into the underlying segment.
|
||||
|
||||
@ -26,16 +26,21 @@
|
||||
package jdk.incubator.foreign;
|
||||
|
||||
import jdk.internal.foreign.LayoutPath;
|
||||
import jdk.internal.foreign.LayoutPath.PathElementImpl.PathKind;
|
||||
import jdk.internal.foreign.Utils;
|
||||
|
||||
import java.lang.constant.Constable;
|
||||
import java.lang.constant.DynamicConstantDesc;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* A memory layout can be used to describe the contents of a memory segment in a <em>language neutral</em> fashion.
|
||||
@ -87,9 +92,11 @@ import java.util.OptionalLong;
|
||||
* at a layout nested within the root layout - this is the layout <em>selected</em> by the layout path.
|
||||
* Layout paths are typically expressed as a sequence of one or more {@link PathElement} instances.
|
||||
* <p>
|
||||
* Layout paths are useful in order to e.g. to obtain offset of leaf elements inside arbitrarily nested layouts
|
||||
* (see {@link MemoryLayout#offset(PathElement...)}), or to quickly obtain a memory access handle corresponding to the selected
|
||||
* layout (see {@link MemoryLayout#varHandle(Class, PathElement...)}).
|
||||
* Layout paths are for example useful in order to obtain offsets of arbitrarily nested layouts inside another layout
|
||||
* (see {@link MemoryLayout#offset(PathElement...)}), to quickly obtain a memory access handle corresponding to the selected
|
||||
* layout (see {@link MemoryLayout#varHandle(Class, PathElement...)}), to select an arbitrarily nested layout inside
|
||||
* another layout (see {@link MemoryLayout#select(PathElement...)}, or to transform a nested layout element inside
|
||||
* another layout (see {@link MemoryLayout#map(UnaryOperator, PathElement...)}).
|
||||
* <p>
|
||||
* Such <em>layout paths</em> can be constructed programmatically using the methods in this class.
|
||||
* For instance, given a layout constructed as follows:
|
||||
@ -104,13 +111,39 @@ SequenceLayout seq = MemoryLayout.ofSequence(5,
|
||||
* We can obtain the offset of the member layout named <code>value</code> from <code>seq</code>, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
long valueOffset = seq.offset(PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* Similarly, we can select the member layout named {@code value}, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout value = seq.select(PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* And, we can also replace the layout named {@code value} with another layout, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout newSeq = seq.map(l -> MemoryLayout.ofPadding(32), PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* That is, the above declaration is identical to the following, more verbose one:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout newSeq = MemoryLayout.ofSequence(5,
|
||||
MemoryLayout.ofStruct(
|
||||
MemoryLayout.ofPaddingBits(32),
|
||||
MemoryLayout.ofPaddingBits(32)
|
||||
));
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* Layout paths can feature one or more <em>free dimensions</em>. For instance, a layout path traversing
|
||||
* an unspecified sequence element (that is, where one of the path component was obtained with the
|
||||
* {@link PathElement#sequenceElement()} method) features an additional free dimension, which will have to be bound at runtime;
|
||||
* that is, the memory access var handle associated with such a layout path expression will feature an extra {@code long}
|
||||
* access coordinate. The layout path constructed in the above example features exactly one free dimension.
|
||||
* {@link PathElement#sequenceElement()} method) features an additional free dimension, which will have to be bound at runtime.
|
||||
* This is important when obtaining memory access var handle from layouts, as in the following code:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
VarHandle valueHandle = seq.map(int.class, PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* Since the layout path {@code seq} constructed in the above example features exactly one free dimension,
|
||||
* it follows that the memory access var handle {@code valueHandle} will feature an extra {@code long}
|
||||
* access coordinate.
|
||||
*
|
||||
* @apiNote In the future, if the Java language permits, {@link MemoryLayout}
|
||||
* may become a {@code sealed} interface, which would prohibit subclassing except by
|
||||
@ -132,6 +165,17 @@ public interface MemoryLayout extends Constable {
|
||||
@Override
|
||||
Optional<? extends DynamicConstantDesc<? extends MemoryLayout>> describeConstable();
|
||||
|
||||
/**
|
||||
* Does this layout have a specified size? A layout does not have a specified size if it is (or contains) a sequence layout whose
|
||||
* size is unspecified (see {@link SequenceLayout#elementCount()}).
|
||||
*
|
||||
* Value layouts (see {@link ValueLayout}) and padding layouts (see {@link MemoryLayout#ofPaddingBits(long)})
|
||||
* <em>always</em> have a specified size, therefore this method always returns {@code true} in these cases.
|
||||
*
|
||||
* @return {@code true}, if this layout has a specified size.
|
||||
*/
|
||||
boolean hasSize();
|
||||
|
||||
/**
|
||||
* Computes the layout size, in bits.
|
||||
*
|
||||
@ -219,23 +263,21 @@ public interface MemoryLayout extends Constable {
|
||||
MemoryLayout withBitAlignment(long bitAlignment);
|
||||
|
||||
/**
|
||||
* Computes the offset of the layout selected by a given layout path, where the path is considered rooted in this
|
||||
* Computes the offset, in bits, of the layout selected by a given layout path, where the path is considered rooted in this
|
||||
* layout.
|
||||
*
|
||||
* @apiNote if the layout path has one (or more) free dimensions,
|
||||
* the offset is computed as if all the indices corresponding to such dimensions were set to {@code 0}.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return The offset of layout selected by a the layout path obtained by concatenating the path elements in {@code elements}.
|
||||
* @throws IllegalArgumentException if the layout path obtained by concatenating the path elements in {@code elements}
|
||||
* does not select a valid layout element.
|
||||
* @return The offset, in bits, of the layout selected by the layout path in {@code elements}.
|
||||
* @throws IllegalArgumentException if the layout path does not select any layout nested in this layout, or if the
|
||||
* layout path contains one or more path elements that select multiple sequence element indices
|
||||
* (see {@link PathElement#sequenceElement()} and {@link PathElement#sequenceElement(long, long)}).
|
||||
* @throws UnsupportedOperationException if one of the layouts traversed by the layout path has unspecified size.
|
||||
*/
|
||||
default long offset(PathElement... elements) {
|
||||
LayoutPath path = LayoutPath.rootPath(this);
|
||||
for (PathElement e : elements) {
|
||||
path = ((LayoutPath.PathElementImpl)e).apply(path);
|
||||
}
|
||||
return path.offset();
|
||||
return computePathOp(LayoutPath.rootPath(this, MemoryLayout::bitSize), LayoutPath::offset, EnumSet.of(PathKind.SEQUENCE_ELEMENT, PathKind.SEQUENCE_RANGE), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,19 +290,59 @@ public interface MemoryLayout extends Constable {
|
||||
*
|
||||
* @param carrier the var handle carrier type.
|
||||
* @param elements the layout path elements.
|
||||
* @return a var handle which can be used to dereference memory at the layout denoted by given layout path.
|
||||
* @throws UnsupportedOperationException if the layout path has one or more elements with incompatible alignment constraints.
|
||||
* @return a var handle which can be used to dereference memory at the (possibly nested) layout selected by the layout path in {@code elements}.
|
||||
* @throws UnsupportedOperationException if the layout path has one or more elements with incompatible alignment constraints,
|
||||
* or if one of the layouts traversed by the layout path has unspecified size.
|
||||
* @throws IllegalArgumentException if the carrier does not represent a primitive type, if the carrier is {@code void},
|
||||
* {@code boolean}, or if the layout path obtained by concatenating the path elements in {@code elements}
|
||||
* does not select a value layout (see {@link ValueLayout}), or if the selected value layout has a size that
|
||||
* that does not match that of the specified carrier type.
|
||||
* {@code boolean}, or if the layout path in {@code elements} does not select a value layout (see {@link ValueLayout}),
|
||||
* or if the selected value layout has a size that that does not match that of the specified carrier type.
|
||||
*/
|
||||
default VarHandle varHandle(Class<?> carrier, PathElement... elements) {
|
||||
LayoutPath path = LayoutPath.rootPath(this);
|
||||
return computePathOp(LayoutPath.rootPath(this, MemoryLayout::bitSize), path -> path.dereferenceHandle(carrier),
|
||||
Set.of(), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the layout from a path rooted in this layout.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return the layout selected by the layout path in {@code elements}.
|
||||
* @throws IllegalArgumentException if the layout path does not select any layout nested in this layout,
|
||||
* or if the layout path contains one or more path elements that select one or more sequence element indices
|
||||
* (see {@link PathElement#sequenceElement(long)} and {@link PathElement#sequenceElement(long, long)}).
|
||||
*/
|
||||
default MemoryLayout select(PathElement... elements) {
|
||||
return computePathOp(LayoutPath.rootPath(this, l -> 0L), LayoutPath::layout,
|
||||
EnumSet.of(PathKind.SEQUENCE_ELEMENT_INDEX, PathKind.SEQUENCE_RANGE), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transformed copy of this layout where a selected layout, from a path rooted in this layout,
|
||||
* is replaced with the result of applying the given operation.
|
||||
*
|
||||
* @param op the unary operation to be applied to the selected layout.
|
||||
* @param elements the layout path elements.
|
||||
* @return a new layout where the layout selected by the layout path in {@code elements},
|
||||
* has been replaced by the result of applying {@code op} to the selected layout.
|
||||
* @throws IllegalArgumentException if the layout path does not select any layout nested in this layout,
|
||||
* or if the layout path contains one or more path elements that select one or more sequence element indices
|
||||
* (see {@link PathElement#sequenceElement(long)} and {@link PathElement#sequenceElement(long, long)}).
|
||||
*/
|
||||
default MemoryLayout map(UnaryOperator<MemoryLayout> op, PathElement... elements) {
|
||||
return computePathOp(LayoutPath.rootPath(this, l -> 0L), path -> path.map(op),
|
||||
EnumSet.of(PathKind.SEQUENCE_ELEMENT_INDEX, PathKind.SEQUENCE_RANGE), elements);
|
||||
}
|
||||
|
||||
private static <Z> Z computePathOp(LayoutPath path, Function<LayoutPath, Z> finalizer,
|
||||
Set<LayoutPath.PathElementImpl.PathKind> badKinds, PathElement... elements) {
|
||||
for (PathElement e : elements) {
|
||||
path = ((LayoutPath.PathElementImpl)e).apply(path);
|
||||
LayoutPath.PathElementImpl pathElem = (LayoutPath.PathElementImpl)e;
|
||||
if (badKinds.contains(pathElem.kind())) {
|
||||
throw new IllegalArgumentException(String.format("Invalid %s selection in layout path", pathElem.kind().description()));
|
||||
}
|
||||
path = pathElem.apply(path);
|
||||
}
|
||||
return path.dereferenceHandle(carrier);
|
||||
return finalizer.apply(path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,7 +379,8 @@ public interface MemoryLayout extends Constable {
|
||||
*/
|
||||
static PathElement groupElement(String name) {
|
||||
Objects.requireNonNull(name);
|
||||
return new LayoutPath.PathElementImpl(path -> path.groupElement(name));
|
||||
return new LayoutPath.PathElementImpl(LayoutPath.PathElementImpl.PathKind.GROUP_ELEMENT,
|
||||
path -> path.groupElement(name));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +396,8 @@ public interface MemoryLayout extends Constable {
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("Index must be positive: " + index);
|
||||
}
|
||||
return new LayoutPath.PathElementImpl(path -> path.sequenceElement(index));
|
||||
return new LayoutPath.PathElementImpl(LayoutPath.PathElementImpl.PathKind.SEQUENCE_ELEMENT_INDEX,
|
||||
path -> path.sequenceElement(index));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -341,7 +425,8 @@ E * (S + I * F)
|
||||
if (step == 0) {
|
||||
throw new IllegalArgumentException("Step must be != 0: " + step);
|
||||
}
|
||||
return new LayoutPath.PathElementImpl(path -> path.sequenceElement(start, step));
|
||||
return new LayoutPath.PathElementImpl(LayoutPath.PathElementImpl.PathKind.SEQUENCE_RANGE,
|
||||
path -> path.sequenceElement(start, step));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,7 +437,8 @@ E * (S + I * F)
|
||||
* @return a path element which selects an unspecified sequence element layout.
|
||||
*/
|
||||
static PathElement sequenceElement() {
|
||||
return new LayoutPath.PathElementImpl(LayoutPath::sequenceElement);
|
||||
return new LayoutPath.PathElementImpl(LayoutPath.PathElementImpl.PathKind.SEQUENCE_ELEMENT,
|
||||
LayoutPath::sequenceElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ import java.nio.ByteOrder;
|
||||
* This class defines useful layout constants. Some of the constants defined in this class are explicit in both
|
||||
* size and byte order (see {@link #BITS_64_BE}), and can therefore be used to explicitly and unambiguously specify the
|
||||
* contents of a memory segment. Other constants make implicit byte order assumptions (see
|
||||
* {@link #JAVA_INT}); as such, these constants make it easy to interoperate with other serialization-centric APIs,
|
||||
* {@link #JAVA_INT}); as such, these constants make it easy to work with other serialization-centric APIs,
|
||||
* such as {@link java.nio.ByteBuffer}.
|
||||
*/
|
||||
public final class MemoryLayouts {
|
||||
|
||||
@ -145,10 +145,10 @@ public interface MemorySegment extends AutoCloseable {
|
||||
MemorySegment acquire();
|
||||
|
||||
/**
|
||||
* Is this segment accessible from the current thread?
|
||||
* @return true, if this segment is accessible from the current thread.
|
||||
* The thread owning this segment.
|
||||
* @return the thread owning this segment.
|
||||
*/
|
||||
boolean isAccessible();
|
||||
Thread ownerThread();
|
||||
|
||||
/**
|
||||
* The size (in bytes) of this memory segment.
|
||||
|
||||
@ -95,6 +95,18 @@ public final class SequenceLayout extends AbstractLayout {
|
||||
return elemCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a new sequence layout with same element layout, alignment constraints and name as this sequence layout
|
||||
* but with the new specified element count.
|
||||
* @param elementCount the new element count.
|
||||
* @return a new sequence with given element count.
|
||||
* @throws IllegalArgumentException if {@code elementCount < 0}.
|
||||
*/
|
||||
public SequenceLayout withElementCount(long elementCount) {
|
||||
AbstractLayout.checkSize(elementCount, true);
|
||||
return new SequenceLayout(OptionalLong.of(elementCount), elementLayout, alignment, name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return decorateLayoutString(String.format("[%s:%s]",
|
||||
|
||||
@ -34,6 +34,9 @@ import jdk.incubator.foreign.GroupLayout;
|
||||
import jdk.incubator.foreign.SequenceLayout;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.ToLongFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
@ -53,12 +56,16 @@ public class LayoutPath {
|
||||
private final long offset;
|
||||
private final LayoutPath enclosing;
|
||||
private final long[] strides;
|
||||
private final long elementIndex;
|
||||
private final ToLongFunction<MemoryLayout> sizeFunc;
|
||||
|
||||
private LayoutPath(MemoryLayout layout, long offset, long[] strides, LayoutPath enclosing) {
|
||||
private LayoutPath(MemoryLayout layout, long offset, long[] strides, long elementIndex, LayoutPath enclosing, ToLongFunction<MemoryLayout> sizeFunc) {
|
||||
this.layout = layout;
|
||||
this.offset = offset;
|
||||
this.strides = strides;
|
||||
this.enclosing = enclosing;
|
||||
this.elementIndex = elementIndex;
|
||||
this.sizeFunc = sizeFunc;
|
||||
}
|
||||
|
||||
// Layout path selector methods
|
||||
@ -67,7 +74,7 @@ public class LayoutPath {
|
||||
check(SequenceLayout.class, "attempting to select a sequence element from a non-sequence layout");
|
||||
SequenceLayout seq = (SequenceLayout)layout;
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
return LayoutPath.nestedPath(elem, offset, addStride(elem.bitSize()), this);
|
||||
return LayoutPath.nestedPath(elem, offset, addStride(sizeFunc.applyAsLong(elem)), -1, this);
|
||||
}
|
||||
|
||||
public LayoutPath sequenceElement(long start, long step) {
|
||||
@ -75,8 +82,8 @@ public class LayoutPath {
|
||||
SequenceLayout seq = (SequenceLayout)layout;
|
||||
checkSequenceBounds(seq, start);
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
long elemSize = elem.bitSize();
|
||||
return LayoutPath.nestedPath(elem, offset + (start * elemSize), addStride(elemSize * step), this);
|
||||
long elemSize = sizeFunc.applyAsLong(elem);
|
||||
return LayoutPath.nestedPath(elem, offset + (start * elemSize), addStride(elemSize * step), -1, this);
|
||||
}
|
||||
|
||||
public LayoutPath sequenceElement(long index) {
|
||||
@ -86,10 +93,10 @@ public class LayoutPath {
|
||||
long elemOffset = 0;
|
||||
if (index > 0) {
|
||||
//if index == 0, we do not depend on sequence element size, so skip
|
||||
long elemSize = seq.elementLayout().bitSize();
|
||||
long elemSize = sizeFunc.applyAsLong(seq.elementLayout());
|
||||
elemOffset = elemSize * index;
|
||||
}
|
||||
return LayoutPath.nestedPath(seq.elementLayout(), offset + elemOffset, strides, this);
|
||||
return LayoutPath.nestedPath(seq.elementLayout(), offset + elemOffset, strides, index, this);
|
||||
}
|
||||
|
||||
public LayoutPath groupElement(String name) {
|
||||
@ -97,20 +104,22 @@ public class LayoutPath {
|
||||
GroupLayout g = (GroupLayout)layout;
|
||||
long offset = 0;
|
||||
MemoryLayout elem = null;
|
||||
int index = -1;
|
||||
for (int i = 0; i < g.memberLayouts().size(); i++) {
|
||||
MemoryLayout l = g.memberLayouts().get(i);
|
||||
if (l.name().isPresent() &&
|
||||
l.name().get().equals(name)) {
|
||||
elem = l;
|
||||
index = i;
|
||||
break;
|
||||
} else {
|
||||
offset += l.bitSize();
|
||||
} else if (g.isStruct()) {
|
||||
offset += sizeFunc.applyAsLong(l);
|
||||
}
|
||||
}
|
||||
if (elem == null) {
|
||||
throw badLayoutPath("cannot resolve '" + name + "' in layout " + layout);
|
||||
}
|
||||
return LayoutPath.nestedPath(elem, this.offset + offset, strides, this);
|
||||
return LayoutPath.nestedPath(elem, this.offset + offset, strides, index, this);
|
||||
}
|
||||
|
||||
// Layout path projections
|
||||
@ -139,14 +148,52 @@ public class LayoutPath {
|
||||
LongStream.of(strides).map(s -> Utils.bitsToBytesOrThrow(s, IllegalStateException::new)).toArray());
|
||||
}
|
||||
|
||||
// Layout path construction
|
||||
|
||||
public static LayoutPath rootPath(MemoryLayout layout) {
|
||||
return new LayoutPath(layout, 0L, EMPTY_STRIDES, null);
|
||||
public MemoryLayout layout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
private static LayoutPath nestedPath(MemoryLayout layout, long offset, long[] strides, LayoutPath encl) {
|
||||
return new LayoutPath(layout, offset, strides, encl);
|
||||
public MemoryLayout map(UnaryOperator<MemoryLayout> op) {
|
||||
MemoryLayout newLayout = op.apply(layout);
|
||||
if (enclosing == null) {
|
||||
return newLayout;
|
||||
} else if (enclosing.layout instanceof SequenceLayout) {
|
||||
SequenceLayout seq = (SequenceLayout)enclosing.layout;
|
||||
if (seq.elementCount().isPresent()) {
|
||||
return enclosing.map(l -> dup(l, MemoryLayout.ofSequence(seq.elementCount().getAsLong(), newLayout)));
|
||||
} else {
|
||||
return enclosing.map(l -> dup(l, MemoryLayout.ofSequence(newLayout)));
|
||||
}
|
||||
} else if (enclosing.layout instanceof GroupLayout) {
|
||||
GroupLayout g = (GroupLayout)enclosing.layout;
|
||||
List<MemoryLayout> newElements = new ArrayList<>(g.memberLayouts());
|
||||
//if we selected a layout in a group we must have a valid index
|
||||
newElements.set((int)elementIndex, newLayout);
|
||||
if (g.isUnion()) {
|
||||
return enclosing.map(l -> dup(l, MemoryLayout.ofUnion(newElements.toArray(new MemoryLayout[0]))));
|
||||
} else {
|
||||
return enclosing.map(l -> dup(l, MemoryLayout.ofStruct(newElements.toArray(new MemoryLayout[0]))));
|
||||
}
|
||||
} else {
|
||||
return newLayout;
|
||||
}
|
||||
}
|
||||
|
||||
private MemoryLayout dup(MemoryLayout oldLayout, MemoryLayout newLayout) {
|
||||
newLayout = newLayout.withBitAlignment(oldLayout.bitAlignment());
|
||||
if (oldLayout.name().isPresent()) {
|
||||
newLayout.withName(oldLayout.name().get());
|
||||
}
|
||||
return newLayout;
|
||||
}
|
||||
|
||||
// Layout path construction
|
||||
|
||||
public static LayoutPath rootPath(MemoryLayout layout, ToLongFunction<MemoryLayout> sizeFunc) {
|
||||
return new LayoutPath(layout, 0L, EMPTY_STRIDES, -1, null, sizeFunc);
|
||||
}
|
||||
|
||||
private static LayoutPath nestedPath(MemoryLayout layout, long offset, long[] strides, long elementIndex, LayoutPath encl) {
|
||||
return new LayoutPath(layout, offset, strides, elementIndex, encl, encl.sizeFunc);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
@ -202,9 +249,28 @@ public class LayoutPath {
|
||||
*/
|
||||
public static class PathElementImpl implements MemoryLayout.PathElement, UnaryOperator<LayoutPath> {
|
||||
|
||||
public enum PathKind {
|
||||
SEQUENCE_ELEMENT("unbound sequence element"),
|
||||
SEQUENCE_ELEMENT_INDEX("bound sequence element"),
|
||||
SEQUENCE_RANGE("sequence range"),
|
||||
GROUP_ELEMENT("group element");
|
||||
|
||||
final String description;
|
||||
|
||||
PathKind(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
final PathKind kind;
|
||||
final UnaryOperator<LayoutPath> pathOp;
|
||||
|
||||
public PathElementImpl(UnaryOperator<LayoutPath> pathOp) {
|
||||
public PathElementImpl(PathKind kind, UnaryOperator<LayoutPath> pathOp) {
|
||||
this.kind = kind;
|
||||
this.pathOp = pathOp;
|
||||
}
|
||||
|
||||
@ -212,5 +278,9 @@ public class LayoutPath {
|
||||
public LayoutPath apply(LayoutPath layoutPath) {
|
||||
return pathOp.apply(layoutPath);
|
||||
}
|
||||
|
||||
public PathKind kind() {
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ public final class MemoryAddressImpl implements MemoryAddress, MemoryAddressProx
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryAddress offset(long bytes) {
|
||||
public MemoryAddress addOffset(long bytes) {
|
||||
return new MemoryAddressImpl(segment, offset + bytes);
|
||||
}
|
||||
|
||||
|
||||
@ -110,8 +110,8 @@ public final class MemorySegmentImpl implements MemorySegment, MemorySegmentProx
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccessible() {
|
||||
return owner == Thread.currentThread();
|
||||
public Thread ownerThread() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -106,8 +106,12 @@ abstract class GssKrb5Base extends AbstractSaslImpl {
|
||||
}
|
||||
|
||||
try {
|
||||
MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
|
||||
MessageProp msgProp = new MessageProp(JGSS_QOP, false);
|
||||
byte[] answer = secCtx.unwrap(incoming, start, len, msgProp);
|
||||
if (privacy && !msgProp.getPrivacy()) {
|
||||
throw new SaslException("Privacy not protected");
|
||||
}
|
||||
checkMessageProp("", msgProp);
|
||||
if (logger.isLoggable(Level.FINEST)) {
|
||||
traceOutput(myClassName, "KRB501:Unwrap", "incoming: ",
|
||||
incoming, start, len);
|
||||
@ -162,4 +166,20 @@ abstract class GssKrb5Base extends AbstractSaslImpl {
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
}
|
||||
|
||||
void checkMessageProp(String label, MessageProp msgProp)
|
||||
throws SaslException {
|
||||
if (msgProp.isDuplicateToken()) {
|
||||
throw new SaslException(label + "Duplicate token");
|
||||
}
|
||||
if (msgProp.isGapToken()) {
|
||||
throw new SaslException(label + "Gap token");
|
||||
}
|
||||
if (msgProp.isOldToken()) {
|
||||
throw new SaslException(label + "Old token");
|
||||
}
|
||||
if (msgProp.isUnseqToken()) {
|
||||
throw new SaslException(label + "Token not in sequence");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,8 +228,10 @@ final class GssKrb5Client extends GssKrb5Base implements SaslClient {
|
||||
|
||||
// Received S1 (security layer, server max recv size)
|
||||
|
||||
MessageProp msgProp = new MessageProp(false);
|
||||
byte[] gssOutToken = secCtx.unwrap(challengeData, 0,
|
||||
challengeData.length, new MessageProp(0, false));
|
||||
challengeData.length, msgProp);
|
||||
checkMessageProp("Handshake failure: ", msgProp);
|
||||
|
||||
// First octet is a bit-mask specifying the protections
|
||||
// supported by the server
|
||||
|
||||
@ -252,8 +252,10 @@ final class GssKrb5Server extends GssKrb5Base implements SaslServer {
|
||||
try {
|
||||
// Expecting 4 octets from client selected protection
|
||||
// and client's receive buffer size
|
||||
MessageProp msgProp = new MessageProp(false);
|
||||
byte[] gssOutToken = secCtx.unwrap(responseData, 0,
|
||||
responseData.length, new MessageProp(0, false));
|
||||
responseData.length, msgProp);
|
||||
checkMessageProp("Handshake failure: ", msgProp);
|
||||
|
||||
if (logger.isLoggable(Level.FINER)) {
|
||||
traceOutput(MY_CLASS_NAME, "doHandshake2",
|
||||
|
||||
@ -81,3 +81,5 @@ compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java 8167430 gene
|
||||
compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java 8167430 generic-all
|
||||
compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java 8167430 generic-all
|
||||
|
||||
vmTestbase/vm/mlvm/indy/stress/java/relinkMutableCallSiteFreq/Test.java 8226689 generic-all
|
||||
vmTestbase/vm/mlvm/indy/stress/java/relinkVolatileCallSiteFreq/Test.java 8226689 generic-all
|
||||
|
||||
@ -34,6 +34,10 @@ import jdk.incubator.foreign.MemoryLayout.PathElement;
|
||||
import jdk.incubator.foreign.SequenceLayout;
|
||||
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class TestLayoutPaths {
|
||||
@ -133,5 +137,146 @@ public class TestLayoutPaths {
|
||||
throw new AssertionError(ex); //should fail!
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadSequencePathInOffset() {
|
||||
SequenceLayout seq = MemoryLayout.ofSequence(10, MemoryLayouts.JAVA_INT);
|
||||
// bad path elements
|
||||
for (PathElement e : List.of( PathElement.sequenceElement(), PathElement.sequenceElement(0, 2) )) {
|
||||
try {
|
||||
seq.offset(e);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadSequencePathInSelect() {
|
||||
SequenceLayout seq = MemoryLayout.ofSequence(10, MemoryLayouts.JAVA_INT);
|
||||
for (PathElement e : List.of( PathElement.sequenceElement(0), PathElement.sequenceElement(0, 2) )) {
|
||||
try {
|
||||
seq.select(e);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadSequencePathInMap() {
|
||||
SequenceLayout seq = MemoryLayout.ofSequence(10, MemoryLayouts.JAVA_INT);
|
||||
for (PathElement e : List.of( PathElement.sequenceElement(0), PathElement.sequenceElement(0, 2) )) {
|
||||
try {
|
||||
seq.map(l -> l, e);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPaths() {
|
||||
long[] offsets = { 0, 8, 24, 56 };
|
||||
GroupLayout g = MemoryLayout.ofStruct(
|
||||
MemoryLayouts.JAVA_BYTE.withName("1"),
|
||||
MemoryLayouts.JAVA_CHAR.withName("2"),
|
||||
MemoryLayouts.JAVA_FLOAT.withName("3"),
|
||||
MemoryLayouts.JAVA_LONG.withName("4")
|
||||
);
|
||||
|
||||
// test select
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
MemoryLayout selected = g.select(PathElement.groupElement(String.valueOf(i)));
|
||||
assertTrue(selected == g.memberLayouts().get(i - 1));
|
||||
}
|
||||
|
||||
// test offset
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
long offset = g.offset(PathElement.groupElement(String.valueOf(i)));
|
||||
assertEquals(offsets[i - 1], offset);
|
||||
}
|
||||
|
||||
// test map
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, PathElement.groupElement(String.valueOf(i)));
|
||||
assertTrue(g2.isStruct());
|
||||
for (int j = 0 ; j < 4 ; j++) {
|
||||
if (j == i - 1) {
|
||||
assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE);
|
||||
} else {
|
||||
assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionPaths() {
|
||||
long[] offsets = { 0, 0, 0, 0 };
|
||||
GroupLayout g = MemoryLayout.ofUnion(
|
||||
MemoryLayouts.JAVA_BYTE.withName("1"),
|
||||
MemoryLayouts.JAVA_CHAR.withName("2"),
|
||||
MemoryLayouts.JAVA_FLOAT.withName("3"),
|
||||
MemoryLayouts.JAVA_LONG.withName("4")
|
||||
);
|
||||
|
||||
// test select
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
MemoryLayout selected = g.select(PathElement.groupElement(String.valueOf(i)));
|
||||
assertTrue(selected == g.memberLayouts().get(i - 1));
|
||||
}
|
||||
|
||||
// test offset
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
long offset = g.offset(PathElement.groupElement(String.valueOf(i)));
|
||||
assertEquals(offsets[i - 1], offset);
|
||||
}
|
||||
|
||||
// test map
|
||||
|
||||
for (int i = 1 ; i <= 4 ; i++) {
|
||||
GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, PathElement.groupElement(String.valueOf(i)));
|
||||
assertTrue(g2.isUnion());
|
||||
for (int j = 0 ; j < 4 ; j++) {
|
||||
if (j == i - 1) {
|
||||
assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE);
|
||||
} else {
|
||||
assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequencePaths() {
|
||||
long[] offsets = { 0, 8, 16, 24 };
|
||||
SequenceLayout g = MemoryLayout.ofSequence(4, MemoryLayouts.JAVA_BYTE);
|
||||
|
||||
// test select
|
||||
|
||||
MemoryLayout selected = g.select(PathElement.sequenceElement());
|
||||
assertTrue(selected == MemoryLayouts.JAVA_BYTE);
|
||||
|
||||
// test offset
|
||||
|
||||
for (int i = 0 ; i < 4 ; i++) {
|
||||
long offset = g.offset(PathElement.sequenceElement(i));
|
||||
assertEquals(offsets[i], offset);
|
||||
}
|
||||
|
||||
// test map
|
||||
|
||||
SequenceLayout seq2 = (SequenceLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, PathElement.sequenceElement());
|
||||
assertTrue(seq2.elementLayout() == MemoryLayouts.JAVA_DOUBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ import java.nio.ByteOrder;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.SequenceLayout;
|
||||
import org.testng.annotations.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@ -55,11 +56,13 @@ public class TestLayouts {
|
||||
MemoryLayouts.JAVA_INT.withName("size"),
|
||||
MemoryLayout.ofPaddingBits(32),
|
||||
MemoryLayout.ofSequence(MemoryLayouts.JAVA_DOUBLE).withName("arr"));
|
||||
assertFalse(layout.hasSize());
|
||||
VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size"));
|
||||
VarHandle array_elem_handle = layout.varHandle(double.class,
|
||||
MemoryLayout.PathElement.groupElement("arr"),
|
||||
MemoryLayout.PathElement.sequenceElement());
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(8 + 8 * 4)) {
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(
|
||||
layout.map(l -> ((SequenceLayout)l).withElementCount(4), MemoryLayout.PathElement.groupElement("arr")))) {
|
||||
size_handle.set(segment.baseAddress(), 4);
|
||||
for (int i = 0 ; i < 4 ; i++) {
|
||||
array_elem_handle.set(segment.baseAddress(), i, (double)i);
|
||||
@ -78,12 +81,14 @@ public class TestLayouts {
|
||||
MemoryLayouts.JAVA_INT.withName("size"),
|
||||
MemoryLayout.ofPaddingBits(32),
|
||||
MemoryLayout.ofSequence(1, MemoryLayout.ofSequence(MemoryLayouts.JAVA_DOUBLE)).withName("arr"));
|
||||
assertFalse(layout.hasSize());
|
||||
VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size"));
|
||||
VarHandle array_elem_handle = layout.varHandle(double.class,
|
||||
MemoryLayout.PathElement.groupElement("arr"),
|
||||
MemoryLayout.PathElement.sequenceElement(0),
|
||||
MemoryLayout.PathElement.sequenceElement());
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(8 + 8 * 4)) {
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(
|
||||
layout.map(l -> ((SequenceLayout)l).withElementCount(4), MemoryLayout.PathElement.groupElement("arr"), MemoryLayout.PathElement.sequenceElement()))) {
|
||||
size_handle.set(segment.baseAddress(), 4);
|
||||
for (int i = 0 ; i < 4 ; i++) {
|
||||
array_elem_handle.set(segment.baseAddress(), i, (double)i);
|
||||
@ -135,6 +140,18 @@ public class TestLayouts {
|
||||
layout.hashCode();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadUnboundSequenceLayoutResize() {
|
||||
SequenceLayout seq = MemoryLayout.ofSequence(MemoryLayouts.JAVA_INT);
|
||||
seq.withElementCount(-1);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadBoundSequenceLayoutResize() {
|
||||
SequenceLayout seq = MemoryLayout.ofSequence(10, MemoryLayouts.JAVA_INT);
|
||||
seq.withElementCount(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyGroup() {
|
||||
MemoryLayout struct = MemoryLayout.ofStruct();
|
||||
|
||||
@ -94,7 +94,7 @@ public class TestMemoryAccess {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
checker.check(handle, addr.offset(layout.byteSize()));
|
||||
checker.check(handle, addr.addOffset(layout.byteSize()));
|
||||
throw new AssertionError(); //not ok, out of bounds
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
//ok, should fail (out of bounds)
|
||||
|
||||
@ -69,7 +69,7 @@ public class TestMemoryAlignment {
|
||||
VarHandle vh = aligned.varHandle(int.class);
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(alignedGroup)) {
|
||||
MemoryAddress addr = segment.baseAddress();
|
||||
vh.set(addr.offset(1L), -42);
|
||||
vh.set(addr.addOffset(1L), -42);
|
||||
assertEquals(align, 8); //this is the only case where access is aligned
|
||||
} catch (IllegalStateException ex) {
|
||||
assertNotEquals(align, 8); //if align != 8, access is always unaligned
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
*/
|
||||
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryHandles;
|
||||
import jdk.incubator.foreign.MemoryLayouts;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import org.testng.annotations.DataProvider;
|
||||
@ -36,11 +35,8 @@ import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@ -55,16 +51,16 @@ public class TestMemoryCopy {
|
||||
int size = Math.min(s1.size(), s2.size());
|
||||
//prepare source and target segments
|
||||
for (int i = 0 ; i < size ; i++) {
|
||||
BYTE_HANDLE.set(addr2.offset(i), (byte)0);
|
||||
BYTE_HANDLE.set(addr2.addOffset(i), (byte)0);
|
||||
}
|
||||
for (int i = 0 ; i < size ; i++) {
|
||||
BYTE_HANDLE.set(addr1.offset(i), (byte) i);
|
||||
BYTE_HANDLE.set(addr1.addOffset(i), (byte) i);
|
||||
}
|
||||
//perform copy
|
||||
MemoryAddress.copy(addr1, addr2, size);
|
||||
//check that copy actually worked
|
||||
for (int i = 0 ; i < size ; i++) {
|
||||
assertEquals((byte)i, BYTE_HANDLE.get(addr2.offset(i)));
|
||||
assertEquals((byte)i, BYTE_HANDLE.get(addr2.addOffset(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,11 +26,11 @@
|
||||
* @run testng TestSegments
|
||||
*/
|
||||
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemoryLayouts;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
|
||||
import java.awt.font.LayoutPath;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -41,7 +41,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.LongFunction;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.incubator.foreign.SequenceLayout;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
@ -96,6 +95,32 @@ public class TestSegments {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSlices() {
|
||||
VarHandle byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE)
|
||||
.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
|
||||
try (MemorySegment segment = MemorySegment.allocateNative(10)) {
|
||||
//init
|
||||
for (byte i = 0 ; i < segment.byteSize() ; i++) {
|
||||
byteHandle.set(segment.baseAddress(), (long)i, i);
|
||||
}
|
||||
long start = 0;
|
||||
MemoryAddress base = segment.baseAddress();
|
||||
MemoryAddress last = base.addOffset(10);
|
||||
while (!base.equals(last)) {
|
||||
MemorySegment slice = segment.asSlice(base.offset(), 10 - start);
|
||||
for (long i = start ; i < 10 ; i++) {
|
||||
assertEquals(
|
||||
byteHandle.get(segment.baseAddress(), i),
|
||||
byteHandle.get(slice.baseAddress(), i - start)
|
||||
);
|
||||
}
|
||||
base = base.addOffset(1);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "badSizeAndAlignments")
|
||||
public Object[][] sizesAndAlignments() {
|
||||
return new Object[][] {
|
||||
|
||||
@ -162,7 +162,7 @@ public class TestVarHandleCombinators {
|
||||
for (long j = 0; j < inner_size; j++) {
|
||||
outer_vh.set(segment.baseAddress(), i, j, count);
|
||||
assertEquals(
|
||||
(int)inner_vh.get(segment.baseAddress().offset(i * inner_size * 8), j),
|
||||
(int)inner_vh.get(segment.baseAddress().addOffset(i * inner_size * 8), j),
|
||||
count);
|
||||
count++;
|
||||
}
|
||||
|
||||
@ -6,15 +6,15 @@
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed source the hope that it will be useful, but WITHOUT
|
||||
* 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 source the LICENSE file that
|
||||
* 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 Franklsource St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -41,9 +41,11 @@ import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
/* @test
|
||||
* @bug 8231422
|
||||
* @build GlobalFilterTest SerialFilterTest
|
||||
* @run testng/othervm GlobalFilterTest
|
||||
* @run testng/othervm -Djdk.serialFilter=java.** GlobalFilterTest
|
||||
* @run testng/othervm -Djdk.serialFilter=java.**
|
||||
* -Dexpected-jdk.serialFilter=java.** GlobalFilterTest
|
||||
* @run testng/othervm/policy=security.policy GlobalFilterTest
|
||||
* @run testng/othervm/policy=security.policy
|
||||
* -Djava.security.properties=${test.src}/java.security-extra1
|
||||
@ -53,6 +55,10 @@ import org.testng.annotations.DataProvider;
|
||||
*/
|
||||
@Test
|
||||
public class GlobalFilterTest {
|
||||
private static final String serialPropName = "jdk.serialFilter";
|
||||
private static final String badSerialFilter = "java.lang.StringBuffer;!*";
|
||||
private static final String origSerialFilterProperty =
|
||||
System.setProperty(serialPropName, badSerialFilter);
|
||||
|
||||
/**
|
||||
* DataProvider of patterns and objects derived from the configured process-wide filter.
|
||||
@ -61,8 +67,8 @@ public class GlobalFilterTest {
|
||||
@DataProvider(name="globalPatternElements")
|
||||
Object[][] globalPatternElements() {
|
||||
String globalFilter =
|
||||
System.getProperty("jdk.serialFilter",
|
||||
Security.getProperty("jdk.serialFilter"));
|
||||
System.getProperty("expected-" + serialPropName,
|
||||
Security.getProperty(serialPropName));
|
||||
if (globalFilter == null) {
|
||||
return new Object[0][];
|
||||
}
|
||||
@ -99,12 +105,20 @@ public class GlobalFilterTest {
|
||||
*/
|
||||
@Test()
|
||||
static void globalFilter() {
|
||||
String pattern =
|
||||
System.getProperty("jdk.serialFilter",
|
||||
Security.getProperty("jdk.serialFilter"));
|
||||
ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter();
|
||||
|
||||
// Check that the System.setProperty(jdk.serialFilter) DOES NOT affect the filter.
|
||||
String asSetSystemProp = System.getProperty(serialPropName,
|
||||
Security.getProperty(serialPropName));
|
||||
Assert.assertNotEquals(Objects.toString(filter, null), asSetSystemProp,
|
||||
"System.setProperty(\"jdk.serialfilter\", ...) should not change filter: " +
|
||||
asSetSystemProp);
|
||||
|
||||
String pattern =
|
||||
System.getProperty("expected-" + serialPropName,
|
||||
Security.getProperty(serialPropName));
|
||||
System.out.printf("global pattern: %s, filter: %s%n", pattern, filter);
|
||||
Assert.assertEquals(pattern, Objects.toString(filter, null),
|
||||
Assert.assertEquals(Objects.toString(filter, null), pattern,
|
||||
"process-wide filter pattern does not match");
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ grant {
|
||||
permission java.io.SerializablePermission "serialFilter";
|
||||
|
||||
// Permissions needed to run the test
|
||||
permission java.util.PropertyPermission "*", "read";
|
||||
permission java.util.PropertyPermission "*", "read,write";
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
permission java.security.SecurityPermission "*";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -23,23 +23,41 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4851777
|
||||
* @bug 4851777 8233452
|
||||
* @summary Tests of BigDecimal.sqrt().
|
||||
*/
|
||||
|
||||
import java.math.*;
|
||||
import java.util.*;
|
||||
|
||||
import static java.math.BigDecimal.ONE;
|
||||
import static java.math.BigDecimal.TEN;
|
||||
import static java.math.BigDecimal.ZERO;
|
||||
import static java.math.BigDecimal.valueOf;
|
||||
|
||||
public class SquareRootTests {
|
||||
private static BigDecimal TWO = new BigDecimal(2);
|
||||
|
||||
/**
|
||||
* The value 0.1, with a scale of 1.
|
||||
*/
|
||||
private static final BigDecimal ONE_TENTH = valueOf(1L, 1);
|
||||
|
||||
public static void main(String... args) {
|
||||
int failures = 0;
|
||||
|
||||
failures += negativeTests();
|
||||
failures += zeroTests();
|
||||
failures += oneDigitTests();
|
||||
failures += twoDigitTests();
|
||||
failures += evenPowersOfTenTests();
|
||||
failures += squareRootTwoTests();
|
||||
failures += lowPrecisionPerfectSquares();
|
||||
failures += almostFourRoundingDown();
|
||||
failures += almostFourRoundingUp();
|
||||
failures += nearTen();
|
||||
failures += nearOne();
|
||||
failures += halfWay();
|
||||
|
||||
if (failures > 0 ) {
|
||||
throw new RuntimeException("Incurred " + failures + " failures" +
|
||||
@ -83,6 +101,74 @@ public class SquareRootTests {
|
||||
return failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe inputs with one digit of precision, 1 ... 9 and those
|
||||
* values scaled by 10^-1, 0.1, ... 0.9.
|
||||
*/
|
||||
private static int oneDigitTests() {
|
||||
int failures = 0;
|
||||
|
||||
List<BigDecimal> oneToNine =
|
||||
List.of(ONE, TWO, valueOf(3),
|
||||
valueOf(4), valueOf(5), valueOf(6),
|
||||
valueOf(7), valueOf(8), valueOf(9));
|
||||
|
||||
List<RoundingMode> modes =
|
||||
List.of(RoundingMode.UP, RoundingMode.DOWN,
|
||||
RoundingMode.CEILING, RoundingMode.FLOOR,
|
||||
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
|
||||
|
||||
for (int i = 1; i < 20; i++) {
|
||||
for (RoundingMode rm : modes) {
|
||||
for (BigDecimal bd : oneToNine) {
|
||||
MathContext mc = new MathContext(i, rm);
|
||||
|
||||
failures += compareSqrtImplementations(bd, mc);
|
||||
bd = bd.multiply(ONE_TENTH);
|
||||
failures += compareSqrtImplementations(bd, mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe inputs with two digits of precision, (10 ... 99) and
|
||||
* those values scaled by 10^-1 (1, ... 9.9) and scaled by 10^-2
|
||||
* (0.1 ... 0.99).
|
||||
*/
|
||||
private static int twoDigitTests() {
|
||||
int failures = 0;
|
||||
|
||||
List<RoundingMode> modes =
|
||||
List.of(RoundingMode.UP, RoundingMode.DOWN,
|
||||
RoundingMode.CEILING, RoundingMode.FLOOR,
|
||||
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
|
||||
|
||||
for (int i = 10; i < 100; i++) {
|
||||
BigDecimal bd0 = BigDecimal.valueOf(i);
|
||||
BigDecimal bd1 = bd0.multiply(ONE_TENTH);
|
||||
BigDecimal bd2 = bd1.multiply(ONE_TENTH);
|
||||
|
||||
for (BigDecimal bd : List.of(bd0, bd1, bd2)) {
|
||||
for (int precision = 1; i < 20; i++) {
|
||||
for (RoundingMode rm : modes) {
|
||||
MathContext mc = new MathContext(precision, rm);
|
||||
failures += compareSqrtImplementations(bd, mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int compareSqrtImplementations(BigDecimal bd, MathContext mc) {
|
||||
return equalNumerically(BigSquareRoot.sqrt(bd, mc),
|
||||
bd.sqrt(mc), "sqrt(" + bd + ") under " + mc);
|
||||
}
|
||||
|
||||
/**
|
||||
* sqrt(10^2N) is 10^N
|
||||
* Both numerical value and representation should be verified
|
||||
@ -92,28 +178,26 @@ public class SquareRootTests {
|
||||
MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY);
|
||||
|
||||
for (int scale = -100; scale <= 100; scale++) {
|
||||
BigDecimal testValue = BigDecimal.valueOf(1, 2*scale);
|
||||
BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale);
|
||||
BigDecimal testValue = BigDecimal.valueOf(1, 2*scale);
|
||||
BigDecimal expectedNumericalResult = BigDecimal.valueOf(1, scale);
|
||||
|
||||
BigDecimal result;
|
||||
|
||||
|
||||
failures += equalNumerically(expectedNumericalResult,
|
||||
result = testValue.sqrt(MathContext.DECIMAL64),
|
||||
"Even powers of 10, DECIMAL64");
|
||||
result = testValue.sqrt(MathContext.DECIMAL64),
|
||||
"Even powers of 10, DECIMAL64");
|
||||
|
||||
// Can round to one digit of precision exactly
|
||||
failures += equalNumerically(expectedNumericalResult,
|
||||
result = testValue.sqrt(oneDigitExactly),
|
||||
"even powers of 10, 1 digit");
|
||||
result = testValue.sqrt(oneDigitExactly),
|
||||
"even powers of 10, 1 digit");
|
||||
|
||||
if (result.precision() > 1) {
|
||||
failures += 1;
|
||||
System.err.println("Excess precision for " + result);
|
||||
}
|
||||
|
||||
|
||||
// If rounding to more than one digit, do precision / scale checking...
|
||||
|
||||
}
|
||||
|
||||
return failures;
|
||||
@ -121,30 +205,31 @@ public class SquareRootTests {
|
||||
|
||||
private static int squareRootTwoTests() {
|
||||
int failures = 0;
|
||||
BigDecimal TWO = new BigDecimal(2);
|
||||
|
||||
// Square root of 2 truncated to 65 digits
|
||||
BigDecimal highPrecisionRoot2 =
|
||||
new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799");
|
||||
|
||||
|
||||
RoundingMode[] modes = {
|
||||
RoundingMode.UP, RoundingMode.DOWN,
|
||||
RoundingMode.CEILING, RoundingMode.FLOOR,
|
||||
RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN
|
||||
};
|
||||
|
||||
// For each iteresting rounding mode, for precisions 1 to, say
|
||||
// 63 numerically compare TWO.sqrt(mc) to
|
||||
// highPrecisionRoot2.round(mc)
|
||||
|
||||
// For each interesting rounding mode, for precisions 1 to, say,
|
||||
// 63 numerically compare TWO.sqrt(mc) to
|
||||
// highPrecisionRoot2.round(mc) and the alternative internal high-precision
|
||||
// implementation of square root.
|
||||
for (RoundingMode mode : modes) {
|
||||
for (int precision = 1; precision < 63; precision++) {
|
||||
MathContext mc = new MathContext(precision, mode);
|
||||
BigDecimal expected = highPrecisionRoot2.round(mc);
|
||||
BigDecimal computed = TWO.sqrt(mc);
|
||||
BigDecimal altComputed = BigSquareRoot.sqrt(TWO, mc);
|
||||
|
||||
equalNumerically(expected, computed, "sqrt(2)");
|
||||
failures += equalNumerically(expected, computed, "sqrt(2)");
|
||||
failures += equalNumerically(computed, altComputed, "computed & altComputed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,8 +266,8 @@ public class SquareRootTests {
|
||||
int computedScale = computedRoot.scale();
|
||||
if (precision >= expectedScale + 1 &&
|
||||
computedScale != expectedScale) {
|
||||
System.err.printf("%s\tprecision=%d\trm=%s%n",
|
||||
computedRoot.toString(), precision, rm);
|
||||
System.err.printf("%s\tprecision=%d\trm=%s%n",
|
||||
computedRoot.toString(), precision, rm);
|
||||
failures++;
|
||||
System.err.printf("\t%s does not have expected scale of %d%n.",
|
||||
computedRoot, expectedScale);
|
||||
@ -195,6 +280,134 @@ public class SquareRootTests {
|
||||
return failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test around 3.9999 that the sqrt doesn't improperly round-up to
|
||||
* a numerical value of 2.
|
||||
*/
|
||||
private static int almostFourRoundingDown() {
|
||||
int failures = 0;
|
||||
BigDecimal nearFour = new BigDecimal("3.999999999999999999999999999999");
|
||||
|
||||
// Sqrt is 1.9999...
|
||||
|
||||
for (int i = 1; i < 64; i++) {
|
||||
MathContext mc = new MathContext(i, RoundingMode.FLOOR);
|
||||
BigDecimal result = nearFour.sqrt(mc);
|
||||
BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
|
||||
failures += equalNumerically(expected, result, "near four rounding down");
|
||||
failures += (result.compareTo(TWO) < 0) ? 0 : 1 ;
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test around 4.000...1 that the sqrt doesn't improperly
|
||||
* round-down to a numerical value of 2.
|
||||
*/
|
||||
private static int almostFourRoundingUp() {
|
||||
int failures = 0;
|
||||
BigDecimal nearFour = new BigDecimal("4.000000000000000000000000000001");
|
||||
|
||||
// Sqrt is 2.0000....<non-zero digits>
|
||||
|
||||
for (int i = 1; i < 64; i++) {
|
||||
MathContext mc = new MathContext(i, RoundingMode.CEILING);
|
||||
BigDecimal result = nearFour.sqrt(mc);
|
||||
BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
|
||||
failures += equalNumerically(expected, result, "near four rounding up");
|
||||
failures += (result.compareTo(TWO) > 0) ? 0 : 1 ;
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int nearTen() {
|
||||
int failures = 0;
|
||||
|
||||
BigDecimal near10 = new BigDecimal("9.99999999999999999999");
|
||||
|
||||
BigDecimal near10sq = near10.multiply(near10);
|
||||
|
||||
BigDecimal near10sq_ulp = near10sq.add(near10sq.ulp());
|
||||
|
||||
for (int i = 10; i < 23; i++) {
|
||||
MathContext mc = new MathContext(i, RoundingMode.HALF_EVEN);
|
||||
|
||||
failures += equalNumerically(BigSquareRoot.sqrt(near10sq_ulp, mc),
|
||||
near10sq_ulp.sqrt(mc),
|
||||
"near 10 rounding half even");
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Probe for rounding failures near a power of ten, 1 = 10^0,
|
||||
* where an ulp has a different size above and below the value.
|
||||
*/
|
||||
private static int nearOne() {
|
||||
int failures = 0;
|
||||
|
||||
BigDecimal near1 = new BigDecimal(".999999999999999999999");
|
||||
BigDecimal near1sq = near1.multiply(near1);
|
||||
BigDecimal near1sq_ulp = near1sq.add(near1sq.ulp());
|
||||
|
||||
for (int i = 10; i < 23; i++) {
|
||||
for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
|
||||
RoundingMode.UP,
|
||||
RoundingMode.DOWN )) {
|
||||
MathContext mc = new MathContext(i, rm);
|
||||
failures += equalNumerically(BigSquareRoot.sqrt(near1sq_ulp, mc),
|
||||
near1sq_ulp.sqrt(mc),
|
||||
mc.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
private static int halfWay() {
|
||||
int failures = 0;
|
||||
|
||||
/*
|
||||
* Use enough digits that the exact result cannot be computed
|
||||
* from the sqrt of a double.
|
||||
*/
|
||||
BigDecimal[] halfWayCases = {
|
||||
// Odd next digit, truncate on HALF_EVEN
|
||||
new BigDecimal("123456789123456789.5"),
|
||||
|
||||
// Even next digit, round up on HALF_EVEN
|
||||
new BigDecimal("123456789123456788.5"),
|
||||
};
|
||||
|
||||
for (BigDecimal halfWayCase : halfWayCases) {
|
||||
// Round result to next-to-last place
|
||||
int precision = halfWayCase.precision() - 1;
|
||||
BigDecimal square = halfWayCase.multiply(halfWayCase);
|
||||
|
||||
for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
|
||||
RoundingMode.HALF_UP,
|
||||
RoundingMode.HALF_DOWN)) {
|
||||
MathContext mc = new MathContext(precision, rm);
|
||||
|
||||
System.out.println("\nRounding mode " + rm);
|
||||
System.out.println("\t" + halfWayCase.round(mc) + "\t" + halfWayCase);
|
||||
System.out.println("\t" + BigSquareRoot.sqrt(square, mc));
|
||||
|
||||
failures += equalNumerically(/*square.sqrt(mc),*/
|
||||
BigSquareRoot.sqrt(square, mc),
|
||||
halfWayCase.round(mc),
|
||||
"Rounding halway " + rm);
|
||||
}
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) {
|
||||
boolean result = a.equals(b);
|
||||
int failed = (result==expected) ? 0 : 1;
|
||||
@ -224,4 +437,306 @@ public class SquareRootTests {
|
||||
return failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative implementation of BigDecimal square root which uses
|
||||
* higher-precision for a simpler set of termination conditions
|
||||
* for the Newton iteration.
|
||||
*/
|
||||
private static class BigSquareRoot {
|
||||
|
||||
/**
|
||||
* The value 0.5, with a scale of 1.
|
||||
*/
|
||||
private static final BigDecimal ONE_HALF = valueOf(5L, 1);
|
||||
|
||||
public static boolean isPowerOfTen(BigDecimal bd) {
|
||||
return BigInteger.ONE.equals(bd.unscaledValue());
|
||||
}
|
||||
|
||||
public static BigDecimal square(BigDecimal bd) {
|
||||
return bd.multiply(bd);
|
||||
}
|
||||
|
||||
public static BigDecimal sqrt(BigDecimal bd, MathContext mc) {
|
||||
int signum = bd.signum();
|
||||
if (signum == 1) {
|
||||
/*
|
||||
* The following code draws on the algorithm presented in
|
||||
* "Properly Rounded Variable Precision Square Root," Hull and
|
||||
* Abrham, ACM Transactions on Mathematical Software, Vol 11,
|
||||
* No. 3, September 1985, Pages 229-237.
|
||||
*
|
||||
* The BigDecimal computational model differs from the one
|
||||
* presented in the paper in several ways: first BigDecimal
|
||||
* numbers aren't necessarily normalized, second many more
|
||||
* rounding modes are supported, including UNNECESSARY, and
|
||||
* exact results can be requested.
|
||||
*
|
||||
* The main steps of the algorithm below are as follows,
|
||||
* first argument reduce the value to the numerical range
|
||||
* [1, 10) using the following relations:
|
||||
*
|
||||
* x = y * 10 ^ exp
|
||||
* sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even
|
||||
* sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd
|
||||
*
|
||||
* Then use Newton's iteration on the reduced value to compute
|
||||
* the numerical digits of the desired result.
|
||||
*
|
||||
* Finally, scale back to the desired exponent range and
|
||||
* perform any adjustment to get the preferred scale in the
|
||||
* representation.
|
||||
*/
|
||||
|
||||
// The code below favors relative simplicity over checking
|
||||
// for special cases that could run faster.
|
||||
|
||||
int preferredScale = bd.scale()/2;
|
||||
BigDecimal zeroWithFinalPreferredScale =
|
||||
BigDecimal.valueOf(0L, preferredScale);
|
||||
|
||||
// First phase of numerical normalization, strip trailing
|
||||
// zeros and check for even powers of 10.
|
||||
BigDecimal stripped = bd.stripTrailingZeros();
|
||||
int strippedScale = stripped.scale();
|
||||
|
||||
// Numerically sqrt(10^2N) = 10^N
|
||||
if (isPowerOfTen(stripped) &&
|
||||
strippedScale % 2 == 0) {
|
||||
BigDecimal result = BigDecimal.valueOf(1L, strippedScale/2);
|
||||
if (result.scale() != preferredScale) {
|
||||
// Adjust to requested precision and preferred
|
||||
// scale as appropriate.
|
||||
result = result.add(zeroWithFinalPreferredScale, mc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// After stripTrailingZeros, the representation is normalized as
|
||||
//
|
||||
// unscaledValue * 10^(-scale)
|
||||
//
|
||||
// where unscaledValue is an integer with the mimimum
|
||||
// precision for the cohort of the numerical value. To
|
||||
// allow binary floating-point hardware to be used to get
|
||||
// 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).
|
||||
|
||||
// Now the precision / scale adjustment
|
||||
int scaleAdjust = 0;
|
||||
int scale = stripped.scale() - stripped.precision() + 1;
|
||||
if (scale % 2 == 0) {
|
||||
scaleAdjust = scale;
|
||||
} else {
|
||||
scaleAdjust = scale - 1;
|
||||
}
|
||||
|
||||
BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust);
|
||||
|
||||
assert // Verify 0.1 <= working < 10
|
||||
ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0;
|
||||
|
||||
// Use good ole' Math.sqrt to get the initial guess for
|
||||
// the Newton iteration, good to at least 15 decimal
|
||||
// digits. This approach does incur the cost of a
|
||||
//
|
||||
// BigDecimal -> double -> BigDecimal
|
||||
//
|
||||
// conversion cycle, but it avoids the need for several
|
||||
// Newton iterations in BigDecimal arithmetic to get the
|
||||
// working answer to 15 digits of precision. If many fewer
|
||||
// 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
|
||||
// digits of precision; it depends on the relative density
|
||||
// of binary and decimal numbers at different regions of
|
||||
// the number line.)
|
||||
//
|
||||
// (It would be possible to check for certain special
|
||||
// cases to avoid doing any Newton iterations. For
|
||||
// example, if the BigDecimal -> double conversion was
|
||||
// known to be exact and the rounding mode had a
|
||||
// low-enough precision, the post-Newton rounding logic
|
||||
// could be applied directly.)
|
||||
|
||||
BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue()));
|
||||
int guessPrecision = 15;
|
||||
int originalPrecision = mc.getPrecision();
|
||||
int targetPrecision;
|
||||
|
||||
// If an exact value is requested, it must only need
|
||||
// about half of the input digits to represent since
|
||||
// multiplying an N digit number by itself yield a (2N
|
||||
// - 1) digit or 2N digit result.
|
||||
if (originalPrecision == 0) {
|
||||
targetPrecision = stripped.precision()/2 + 1;
|
||||
} else {
|
||||
targetPrecision = originalPrecision;
|
||||
}
|
||||
|
||||
// When setting the precision to use inside the Newton
|
||||
// iteration loop, take care to avoid the case where the
|
||||
// precision of the input exceeds the requested precision
|
||||
// and rounding the input value too soon.
|
||||
BigDecimal approx = guess;
|
||||
int workingPrecision = working.precision();
|
||||
// Use "2p + 2" property to guarantee enough
|
||||
// intermediate precision so that a double-rounding
|
||||
// error does not occur when rounded to the final
|
||||
// destination precision.
|
||||
int loopPrecision =
|
||||
Math.max(2 * Math.max(targetPrecision, workingPrecision) + 2,
|
||||
34); // Force at least two Netwon
|
||||
// iterations on the Math.sqrt
|
||||
// result.
|
||||
do {
|
||||
MathContext mcTmp = new MathContext(loopPrecision, RoundingMode.HALF_EVEN);
|
||||
// approx = 0.5 * (approx + fraction / approx)
|
||||
approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp));
|
||||
guessPrecision *= 2;
|
||||
} while (guessPrecision < loopPrecision);
|
||||
|
||||
BigDecimal result;
|
||||
RoundingMode targetRm = mc.getRoundingMode();
|
||||
if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) {
|
||||
RoundingMode tmpRm =
|
||||
(targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm;
|
||||
MathContext mcTmp = new MathContext(targetPrecision, tmpRm);
|
||||
result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp);
|
||||
|
||||
// If result*result != this numerically, the square
|
||||
// root isn't exact
|
||||
if (bd.subtract(square(result)).compareTo(ZERO) != 0) {
|
||||
throw new ArithmeticException("Computed square root not exact.");
|
||||
}
|
||||
} else {
|
||||
result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
|
||||
}
|
||||
|
||||
assert squareRootResultAssertions(bd, 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.
|
||||
result = result.stripTrailingZeros().
|
||||
add(zeroWithFinalPreferredScale,
|
||||
new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
switch (signum) {
|
||||
case -1:
|
||||
throw new ArithmeticException("Attempted square root " +
|
||||
"of negative BigDecimal");
|
||||
case 0:
|
||||
return valueOf(0L, bd.scale()/2);
|
||||
|
||||
default:
|
||||
throw new AssertionError("Bad value from signum");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private static boolean squareRootResultAssertions(BigDecimal input, BigDecimal result, MathContext mc) {
|
||||
if (result.signum() == 0) {
|
||||
return squareRootZeroResultAssertions(input, result, mc);
|
||||
} else {
|
||||
RoundingMode rm = mc.getRoundingMode();
|
||||
BigDecimal ulp = result.ulp();
|
||||
BigDecimal neighborUp = result.add(ulp);
|
||||
// Make neighbor down accurate even for powers of ten
|
||||
if (isPowerOfTen(result)) {
|
||||
ulp = ulp.divide(TEN);
|
||||
}
|
||||
BigDecimal neighborDown = result.subtract(ulp);
|
||||
|
||||
// Both the starting value and result should be nonzero and positive.
|
||||
if (result.signum() != 1 ||
|
||||
input.signum() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (rm) {
|
||||
case DOWN:
|
||||
case FLOOR:
|
||||
assert
|
||||
square(result).compareTo(input) <= 0 &&
|
||||
square(neighborUp).compareTo(input) > 0:
|
||||
"Square of result out for bounds rounding " + rm;
|
||||
return true;
|
||||
|
||||
case UP:
|
||||
case CEILING:
|
||||
assert
|
||||
square(result).compareTo(input) >= 0 :
|
||||
"Square of result too small rounding " + rm;
|
||||
|
||||
assert
|
||||
square(neighborDown).compareTo(input) < 0 :
|
||||
"Square of down neighbor too large rounding " + rm + "\n" +
|
||||
"\t input: " + input + "\t neighborDown: " + neighborDown +"\t sqrt: " + result +
|
||||
"\t" + mc;
|
||||
return true;
|
||||
|
||||
|
||||
case HALF_DOWN:
|
||||
case HALF_EVEN:
|
||||
case HALF_UP:
|
||||
BigDecimal err = square(result).subtract(input).abs();
|
||||
BigDecimal errUp = square(neighborUp).subtract(input);
|
||||
BigDecimal errDown = input.subtract(square(neighborDown));
|
||||
// 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);
|
||||
|
||||
assert
|
||||
errUp.signum() == 1 &&
|
||||
errDown.signum() == 1 :
|
||||
"Errors of neighbors squared don't have correct signs";
|
||||
|
||||
// At least one of these must be true, but not both
|
||||
// assert
|
||||
// err_comp_errUp <= 0 : "Upper neighbor is closer than result: " + rm +
|
||||
// "\t" + input + "\t result" + result;
|
||||
// assert
|
||||
// err_comp_errDown <= 0 : "Lower neighbor is closer than result: " + rm +
|
||||
// "\t" + input + "\t result " + result + "\t lower neighbor: " + neighborDown;
|
||||
|
||||
assert
|
||||
((err_comp_errUp == 0 ) ? err_comp_errDown < 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean squareRootZeroResultAssertions(BigDecimal input,
|
||||
BigDecimal result,
|
||||
MathContext mc) {
|
||||
return input.compareTo(ZERO) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,7 @@
|
||||
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
|
||||
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 5029431
|
||||
* 5071718 6231529 6221101 6234263 6535542 6591971 6593946 6795561 7190219
|
||||
* 7199551 8065556 8149469
|
||||
* 7199551 8065556 8149469 8230665
|
||||
* @modules java.base/java.nio:open
|
||||
* java.base/jdk.internal.misc
|
||||
* @author Mark Reinhold
|
||||
|
||||
@ -720,7 +720,7 @@ public class KDC {
|
||||
* @return the key
|
||||
* @throws sun.security.krb5.KrbException for unknown/unsupported etype
|
||||
*/
|
||||
private EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
|
||||
EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
|
||||
throws KrbException {
|
||||
try {
|
||||
// Do not call EncryptionKey.acquireSecretKeys(), otherwise
|
||||
@ -801,7 +801,7 @@ public class KDC {
|
||||
int e2 = eTypes[0]; // etype for outgoing session key
|
||||
int e3 = eTypes[0]; // etype for outgoing ticket
|
||||
|
||||
PAData[] pas = KDCReqDotPAData(tgsReq);
|
||||
PAData[] pas = tgsReq.pAData;
|
||||
|
||||
Ticket tkt = null;
|
||||
EncTicketPart etp = null;
|
||||
@ -832,7 +832,6 @@ public class KDC {
|
||||
for (PAData pa: pas) {
|
||||
if (pa.getType() == Krb5.PA_TGS_REQ) {
|
||||
APReq apReq = new APReq(pa.getValue());
|
||||
EncryptedData ed = apReq.authenticator;
|
||||
tkt = apReq.ticket;
|
||||
int te = tkt.encPart.getEType();
|
||||
EncryptionKey kkey = keyForUser(tkt.sname, te, true);
|
||||
@ -1276,7 +1275,7 @@ public class KDC {
|
||||
outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
|
||||
}
|
||||
|
||||
PAData[] inPAs = KDCReqDotPAData(asReq);
|
||||
PAData[] inPAs = asReq.pAData;
|
||||
List<PAData> enc_outPAs = new ArrayList<>();
|
||||
|
||||
byte[] paEncTimestamp = null;
|
||||
@ -1988,7 +1987,6 @@ public class KDC {
|
||||
}
|
||||
|
||||
// Calling private methods thru reflections
|
||||
private static final Field getPADataField;
|
||||
private static final Field getEType;
|
||||
private static final Constructor<EncryptedData> ctorEncryptedData;
|
||||
private static final Method stringToKey;
|
||||
@ -1998,8 +1996,6 @@ public class KDC {
|
||||
try {
|
||||
ctorEncryptedData = EncryptedData.class.getDeclaredConstructor(DerValue.class);
|
||||
ctorEncryptedData.setAccessible(true);
|
||||
getPADataField = KDCReq.class.getDeclaredField("pAData");
|
||||
getPADataField.setAccessible(true);
|
||||
getEType = KDCReqBody.class.getDeclaredField("eType");
|
||||
getEType.setAccessible(true);
|
||||
stringToKey = EncryptionKey.class.getDeclaredMethod(
|
||||
@ -2021,13 +2017,6 @@ public class KDC {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
private static PAData[] KDCReqDotPAData(KDCReq req) {
|
||||
try {
|
||||
return (PAData[])getPADataField.get(req);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
private static int[] KDCReqBodyDotEType(KDCReqBody body) {
|
||||
try {
|
||||
return (int[]) getEType.get(body);
|
||||
|
||||
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, 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 8012082 8019267 8194486
|
||||
* @summary SASL: auth-conf negotiated, but unencrypted data is accepted,
|
||||
* reset to unencrypt
|
||||
* @library /test/lib
|
||||
* @compile -XDignore.symbol.file SaslGSS.java
|
||||
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
|
||||
* @run main/othervm -Djdk.net.hosts.file=TestHosts SaslGSS
|
||||
*/
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.sasl.AuthorizeCallback;
|
||||
import javax.security.sasl.RealmCallback;
|
||||
import javax.security.sasl.Sasl;
|
||||
import javax.security.sasl.SaslServer;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.ietf.jgss.*;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
|
||||
public class SaslGSS {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
String name = "host." + OneKDC.REALM_LOWER_CASE;
|
||||
|
||||
new OneKDC(null).writeJAASConf();
|
||||
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
|
||||
|
||||
// Client in JGSS so that it can control wrap privacy mode
|
||||
GSSManager m = GSSManager.getInstance();
|
||||
GSSContext sc = m.createContext(
|
||||
m.createName(OneKDC.SERVER, GSSUtil.NT_GSS_KRB5_PRINCIPAL),
|
||||
GSSUtil.GSS_KRB5_MECH_OID,
|
||||
null,
|
||||
GSSContext.DEFAULT_LIFETIME);
|
||||
sc.requestMutualAuth(false);
|
||||
|
||||
// Server in SASL
|
||||
final HashMap props = new HashMap();
|
||||
props.put(Sasl.QOP, "auth-conf");
|
||||
SaslServer ss = Sasl.createSaslServer("GSSAPI", "server",
|
||||
name, props,
|
||||
new CallbackHandler() {
|
||||
public void handle(Callback[] callbacks)
|
||||
throws IOException, UnsupportedCallbackException {
|
||||
for (Callback cb : callbacks) {
|
||||
if (cb instanceof RealmCallback) {
|
||||
((RealmCallback) cb).setText(OneKDC.REALM);
|
||||
} else if (cb instanceof AuthorizeCallback) {
|
||||
((AuthorizeCallback) cb).setAuthorized(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
PrintStream oldErr = System.err;
|
||||
System.setErr(new PrintStream(bout));
|
||||
|
||||
Logger.getLogger("javax.security.sasl").setLevel(Level.ALL);
|
||||
Handler h = new ConsoleHandler();
|
||||
h.setLevel(Level.ALL);
|
||||
Logger.getLogger("javax.security.sasl").addHandler(h);
|
||||
|
||||
byte[] token = new byte[0];
|
||||
|
||||
try {
|
||||
// Handshake
|
||||
token = sc.initSecContext(token, 0, token.length);
|
||||
token = ss.evaluateResponse(token);
|
||||
token = sc.unwrap(token, 0, token.length, new MessageProp(0, false));
|
||||
token[0] = (byte)(((token[0] & 4) != 0) ? 4 : 2);
|
||||
token = sc.wrap(token, 0, token.length, new MessageProp(0, false));
|
||||
ss.evaluateResponse(token);
|
||||
} finally {
|
||||
System.setErr(oldErr);
|
||||
}
|
||||
|
||||
// Talk
|
||||
// 1. Client sends a auth-int message
|
||||
byte[] hello = "hello".getBytes();
|
||||
MessageProp qop = new MessageProp(0, false);
|
||||
token = sc.wrap(hello, 0, hello.length, qop);
|
||||
// 2. Server accepts it anyway
|
||||
ss.unwrap(token, 0, token.length);
|
||||
// 3. Server sends a message
|
||||
token = ss.wrap(hello, 0, hello.length);
|
||||
// 4. Client accepts, should be auth-conf
|
||||
sc.unwrap(token, 0, token.length, qop);
|
||||
if (!qop.getPrivacy()) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
for (String s: bout.toString().split("\\n")) {
|
||||
if (s.contains("KRB5SRV04") && s.contains("NULL")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.out.println("=======================");
|
||||
System.out.println(bout.toString());
|
||||
System.out.println("=======================");
|
||||
throw new Exception("Haven't seen KRB5SRV04 with NULL");
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6802846 8172529
|
||||
* @bug 6802846 8172529 8227758
|
||||
* @summary jarsigner needs enhanced cert validation(options)
|
||||
* @library /test/lib
|
||||
* @run main/timeout=240 ConciseJarsigner
|
||||
@ -227,17 +227,11 @@ public class ConciseJarsigner {
|
||||
+ "a.jar altchain")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// if ca2 is removed, -certchain still work because altchain is a
|
||||
// self-signed entry and it is trusted by jarsigner
|
||||
// if ca2 is removed and cert is imported, -certchain won't work
|
||||
// because this certificate entry is not trusted
|
||||
// save ca2.cert for easy replay
|
||||
kt("-exportcert -file ca2.cert -alias ca2");
|
||||
kt("-delete -alias ca2");
|
||||
js("-strict -keystore ks -storepass changeit "
|
||||
+ "-certchain certchain a.jar altchain")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// if cert is imported, -certchain won't work because this
|
||||
// certificate entry is not trusted
|
||||
kt("-importcert -file certchain -alias altchain -noprompt");
|
||||
js("-strict -keystore ks -storepass changeit "
|
||||
+ "-certchain certchain a.jar altchain")
|
||||
@ -250,8 +244,8 @@ public class ConciseJarsigner {
|
||||
// ==========================================================
|
||||
|
||||
kt("-genkeypair -alias ee -dname CN=ee");
|
||||
kt("-genkeypair -alias caone -dname CN=caone");
|
||||
kt("-genkeypair -alias catwo -dname CN=catwo");
|
||||
kt("-genkeypair -alias caone -dname CN=caone -ext bc:c");
|
||||
kt("-genkeypair -alias catwo -dname CN=catwo -ext bc:c");
|
||||
|
||||
kt("-certreq -alias ee -file ee.req");
|
||||
kt("-certreq -alias catwo -file catwo.req");
|
||||
|
||||
@ -59,7 +59,7 @@ public class DefaultOptions {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
keytool("-genkeypair -dname CN=A -alias a -keyalg rsa")
|
||||
.shouldHaveExitValue(0);
|
||||
keytool("-genkeypair -dname CN=CA -alias ca -keyalg rsa")
|
||||
keytool("-genkeypair -dname CN=CA -alias ca -keyalg rsa -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
keytool("-alias a -certreq -file a.req");
|
||||
keytool("-alias ca -gencert -infile a.req -outfile a.cert");
|
||||
|
||||
@ -59,7 +59,7 @@ public class EC {
|
||||
Files.write(Path.of("A"), List.of("A"));
|
||||
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("A"));
|
||||
|
||||
kt("-alias ca -dname CN=ca -keyalg ec -genkey -validity 300")
|
||||
kt("-alias ca -dname CN=ca -keyalg ec -genkey -validity 300 -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
kt("-alias a -dname CN=a -keyalg ec -genkey")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
@ -90,7 +90,7 @@ public class JavaKeyStoreAliasCaseInsensitive {
|
||||
+ " test-alias-storeHash-case.jks -storepass changeit";
|
||||
SecurityTools.keytool(KEYSTORE_OPTIONS + " -genkeypair -keyalg DSA"
|
||||
+ " -keypass changeit -alias " + ALIAS + "1 -dname CN=" +
|
||||
ALIAS + "1").shouldHaveExitValue(0);
|
||||
ALIAS + "1" + " -ext bc:c").shouldHaveExitValue(0);
|
||||
SecurityTools.keytool(KEYSTORE_OPTIONS + " -genkeypair -keyalg DSA"
|
||||
+ " -keypass changeit -alias " + ALIAS + "2 -dname CN="
|
||||
+ ALIAS + "2").shouldHaveExitValue(0);
|
||||
|
||||
@ -52,7 +52,7 @@ public class OnlyManifest {
|
||||
Files.write(Path.of("manifest"), List.of("Key: Value"));
|
||||
SecurityTools.jar("cvfm a.jar manifest");
|
||||
|
||||
kt("-alias ca -dname CN=ca -genkey -validity 300")
|
||||
kt("-alias ca -dname CN=ca -genkey -validity 300 -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
kt("-alias a -dname CN=a -genkey -validity 300")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -74,6 +74,7 @@ public class TsacertOptionTest extends Test {
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=CA",
|
||||
"-ext", "bc:c",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
keytool(
|
||||
"-genkey",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -44,7 +44,7 @@ public class Warning {
|
||||
|
||||
Files.deleteIfExists(Paths.get("ks"));
|
||||
|
||||
newCert("ca", "-validity 365000");
|
||||
newCert("ca", "-validity 365000", "-ext bc:c");
|
||||
|
||||
recreateJar();
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -53,7 +53,7 @@ public class BadExtendedKeyUsageTest extends Test {
|
||||
// create a certificate whose signer certificate's
|
||||
// ExtendedKeyUsage extension doesn't allow code signing
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -54,7 +54,7 @@ public class BadNetscapeCertTypeTest extends Test {
|
||||
// create a certificate whose signer certificate's
|
||||
// NetscapeCertType extension doesn't allow code signing
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -54,7 +54,7 @@ public class ChainNotValidatedTest extends Test {
|
||||
// Root CA is not checked at all. If the intermediate CA has
|
||||
// BasicConstraints extension set to true, it will be valid.
|
||||
// Otherwise, chain validation will fail.
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(CA2_KEY_ALIAS);
|
||||
issueCert(CA2_KEY_ALIAS,
|
||||
"-ext",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -52,7 +52,7 @@ public class HasExpiringCertTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -51,7 +51,7 @@ public class HasUnsignedEntryTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
issueCert(
|
||||
KEY_ALIAS,
|
||||
|
||||
@ -72,7 +72,7 @@ public class NoTimestampTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
issueCert(KEY_ALIAS,
|
||||
"-validity", Integer.toString(VALIDITY));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -49,7 +49,7 @@ public class NotSignedByAliasTest extends Test {
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
|
||||
// create first key pair for signing
|
||||
createAlias(FIRST_KEY_ALIAS);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2017 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 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
|
||||
@ -35,23 +35,23 @@ public class BadValue {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Test IOUtils.readFully
|
||||
// Test IOUtils.
|
||||
|
||||
// We have 4 bytes
|
||||
InputStream in = new ByteArrayInputStream(new byte[10]);
|
||||
byte[] bs = IOUtils.readFully(in, 4, true);
|
||||
byte[] bs = IOUtils.readExactlyNBytes(in, 4);
|
||||
if (bs.length != 4 || in.available() != 6) {
|
||||
throw new Exception("First read error");
|
||||
}
|
||||
// But only 6 left
|
||||
bs = IOUtils.readFully(in, 10, false);
|
||||
bs = in.readNBytes(10);
|
||||
if (bs.length != 6 || in.available() != 0) {
|
||||
throw new Exception("Second read error");
|
||||
}
|
||||
// MAX length results in exception
|
||||
in = new ByteArrayInputStream(new byte[10]);
|
||||
try {
|
||||
bs = IOUtils.readFully(in, Integer.MAX_VALUE, true);
|
||||
bs = IOUtils.readExactlyNBytes(in, Integer.MAX_VALUE);
|
||||
throw new Exception("No exception on MAX_VALUE length");
|
||||
} catch (EOFException ex) {
|
||||
// this is expected
|
||||
@ -61,7 +61,7 @@ public class BadValue {
|
||||
// -1 length results in exception
|
||||
in = new ByteArrayInputStream(new byte[10]);
|
||||
try {
|
||||
bs = IOUtils.readFully(in, -1, true);
|
||||
bs = IOUtils.readExactlyNBytes(in, -1);
|
||||
throw new Exception("No exception on -1 length");
|
||||
} catch (IOException ex) {
|
||||
// this is expected
|
||||
@ -70,13 +70,13 @@ public class BadValue {
|
||||
// 20>10, readAll means failure
|
||||
in = new ByteArrayInputStream(new byte[10]);
|
||||
try {
|
||||
bs = IOUtils.readFully(in, 20, true);
|
||||
bs = IOUtils.readExactlyNBytes(in, 20);
|
||||
throw new Exception("No exception on EOF");
|
||||
} catch (EOFException e) {
|
||||
// OK
|
||||
}
|
||||
int bignum = 10 * 1024 * 1024;
|
||||
bs = IOUtils.readFully(new SuperSlowStream(bignum), bignum, true);
|
||||
bs = IOUtils.readExactlyNBytes(new SuperSlowStream(bignum), bignum);
|
||||
if (bs.length != bignum) {
|
||||
throw new Exception("Read returned small array");
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user