diff --git a/.hgtags b/.hgtags index 11089cb41c2d38c2079fac2e11460816ce7b5a9d..8d7752645ce794eb7694f3fe51f14feca7b8f333 100644 --- a/.hgtags +++ b/.hgtags @@ -389,6 +389,7 @@ f0d5cb59b0e6a67fa102465458cc4725c6e59089 jdk8u40-b25 d4453d784fb6c52e4ed998b167588551e2fd43c5 jdk8u40-b27 5a45234e0fc14ff943e13dc1f8966818acaeb4de jdk8u40-b31 d8ac13c5eafe422d3425dc1aebebfcdf8ca67e2d jdk8u40-b32 +c7fbbf6133c339fb56f03241de28666774023d5d jdk8u40-b33 1ecc234bd38950a2bc047aa253a5e803f0836a4e jdk8u45-b00 e0c7864bbca3f76cde680722f2ae58dff2bff61d jdk8u45-b01 9505c0392cddbfb905401e9fccc23262edc3254f jdk8u45-b02 @@ -534,17 +535,26 @@ d7cc3225f1050de03b236b92e12c547f21697013 jdk8u72-b11 d841d3fdae44f120883dab0a3a809a054cd0274b jdk8u72-b13 f6d24d424cd2af4d2612f7737d3d9a25f58b882d jdk8u72-b14 f3e86cc607260bae368b52d88d7bc8883ee767e3 jdk8u72-b15 +1d4b343084874b1afa1cdd504b9b1e50bab7f121 jdk8u72-b31 892eb9ab179650b89b7bab6bc42f079391c98624 jdk8u73-b00 9b77d3ca0d66a117c3cc0e0a74b8059545b22f0e jdk8u73-b01 2ab13901d6f14bab0dcf4823d5e378a421fba7e2 jdk8u73-b02 9a843dc6f959f62c61014a3a71ec9aa329f1daf1 jdk8u74-b00 e829ab80dfd828803aa8837411900faeaa1254a5 jdk8u74-b01 32c49f4a16599e376e4e46bb33c7bcc486e52ff3 jdk8u74-b02 +9c828e688240362b6f1b761b619cdaa070462c4e jdk8u74-b31 +6968ca30f8fdc9429fcd56187e16f46b215b474b jdk8u74-b32 +02e1209648050922a5a9f2789d9d359795f6f834 jdk8u77-b00 +f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01 +1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02 +c44179bce874a97e93ffd7b76a226af417e017a4 jdk8u77-b03 +8c3f4e540348daed7263bae092b0e5f212478b00 jdk8u77-b31 1d4b343084874b1afa1cdd504b9b1e50bab7f121 jdk8u72-b31 7cfd2c51c501df909833aa0fb6e40c50c61621ed jdk8u75-b00 9e00a43602f87930c2318b2567002871ad9c59dd jdk8u75-b01 9de301db625bb1b462aad3ebd8347118b94bb728 jdk8u75-b02 dcacefa73649a2d821267b6bff1d70aa10a06801 jdk8u75-b03 +f6cc9dbb5db5883385c91bb71ca02081220aaf3d jdk8u101-b00 de91f05824c5398cb2d2f666ff404aaa165498de jdk8u75-b04 4138b3f27ffea524185a604c3f4f149c7e5ba780 jdk8u75-b05 32f64c19b5fba8beeae5236ca6e480bd8e99698a jdk8u75-b06 @@ -557,6 +567,7 @@ e6f4eb91a1fa895c2f4520e4cca0ae6f2ca14fbb jdk8u75-b09 f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01 1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02 c44179bce874a97e93ffd7b76a226af417e017a4 jdk8u77-b03 +8c3f4e540348daed7263bae092b0e5f212478b00 jdk8u77-b31 71f59a00df6c8f3bd5c6d6631a4988a431adab56 jdk8u91-b00 7ade7a1ab10ff893f62cce9440b4a839aa19c250 jdk8u91-b13 f8725698a870b6be82fad578e78a55910b259975 jdk8u91-b14 @@ -576,6 +587,13 @@ cbafa4c725f9d80fd369dd7979dd97682ae284e6 jdk8u76-b09 ea965fea71f612d65013192aa637d88e05915b10 jdk8u92-b00 cc8d0d6c6f9543120836e70e0aa3fa9c9b6fe0f3 jdk8u92-b13 4f06a20cdc59ce9742e6538ff4b9040baba0778a jdk8u92-b14 +5875e297cfcf18304b4b062dc44fa9be312ad6e8 jdk8u92-b31 +f6cc9dbb5db5883385c91bb71ca02081220aaf3d jdk8u81-b00 +00f8f39308687cde45f23282871c46cc6c2f10b3 jdk8u101-b01 +6042757c329b1b96fa6bc931e09306794f5c50c0 jdk8u101-b02 +25934d0d38fe10383ff22eb3f39bf5e8b9e73ac9 jdk8u101-b03 +ebc56c2e803597ef409a5296addc986b390d934d jdk8u101-b04 +c387bd2fb7db40467bd9aa803c8510a04ca32bae jdk8u101-b05 39baa472e20c13c0eb1243eb5dce589e82f78143 jdk8u76-b00 6ea3aea950d19d803475b3f4d704a2942e71b302 jdk8u76-b01 4de4cffb5988cd68959ce4bbd14c6d4547078c91 jdk8u76-b02 diff --git a/src/share/classes/com/sun/crypto/provider/AESCipher.java b/src/share/classes/com/sun/crypto/provider/AESCipher.java index 32cb3e39d3dfecda66dd43b930d9afde52ef2865..9d11f0091df1ad01eeec4e6503b8677941c676dd 100644 --- a/src/share/classes/com/sun/crypto/provider/AESCipher.java +++ b/src/share/classes/com/sun/crypto/provider/AESCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, 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 @@ -172,6 +172,11 @@ abstract class AESCipher extends CipherSpi { */ private final int fixedKeySize; // in bytes, -1 if no restriction + /* + * needed to enforce ISE thrown when updateAAD is called after update for GCM mode. + */ + private boolean updateCalled; + /** * Creates an instance of AES cipher with default ECB mode and * PKCS5Padding. @@ -304,6 +309,7 @@ abstract class AESCipher extends CipherSpi { protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { checkKeySize(key, fixedKeySize); + updateCalled = false; core.init(opmode, key, random); } @@ -336,6 +342,7 @@ abstract class AESCipher extends CipherSpi { SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { checkKeySize(key, fixedKeySize); + updateCalled = false; core.init(opmode, key, params, random); } @@ -344,6 +351,7 @@ abstract class AESCipher extends CipherSpi { SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { checkKeySize(key, fixedKeySize); + updateCalled = false; core.init(opmode, key, params, random); } @@ -368,6 +376,7 @@ abstract class AESCipher extends CipherSpi { */ protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { + updateCalled = true; return core.update(input, inputOffset, inputLen); } @@ -397,6 +406,7 @@ abstract class AESCipher extends CipherSpi { protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { + updateCalled = true; return core.update(input, inputOffset, inputLen, output, outputOffset); } @@ -433,7 +443,9 @@ abstract class AESCipher extends CipherSpi { */ protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { - return core.doFinal(input, inputOffset, inputLen); + byte[] out = core.doFinal(input, inputOffset, inputLen); + updateCalled = false; + return out; } /** @@ -476,8 +488,10 @@ abstract class AESCipher extends CipherSpi { byte[] output, int outputOffset) throws IllegalBlockSizeException, ShortBufferException, BadPaddingException { - return core.doFinal(input, inputOffset, inputLen, output, - outputOffset); + int outLen = core.doFinal(input, inputOffset, inputLen, output, + outputOffset); + updateCalled = false; + return outLen; } /** @@ -574,6 +588,9 @@ abstract class AESCipher extends CipherSpi { */ @Override protected void engineUpdateAAD(byte[] src, int offset, int len) { + if (core.getMode() == CipherCore.GCM_MODE && updateCalled) { + throw new IllegalStateException("AAD must be supplied before encryption/decryption starts"); + } core.updateAAD(src, offset, len); } @@ -606,6 +623,9 @@ abstract class AESCipher extends CipherSpi { */ @Override protected void engineUpdateAAD(ByteBuffer src) { + if (core.getMode() == CipherCore.GCM_MODE && updateCalled) { + throw new IllegalStateException("AAD must be supplied before encryption/decryption starts"); + } if (src != null) { int aadLen = src.limit() - src.position(); if (aadLen != 0) { diff --git a/src/share/classes/com/sun/crypto/provider/CipherCore.java b/src/share/classes/com/sun/crypto/provider/CipherCore.java index 408da30579cb6985dbe689d872676fb06b680418..79f66cd094e3d6e172a4949c80bcbaa6ae24fc9e 100644 --- a/src/share/classes/com/sun/crypto/provider/CipherCore.java +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, 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 @@ -124,7 +124,7 @@ final class CipherCore { private static final int PCBC_MODE = 4; private static final int CTR_MODE = 5; private static final int CTS_MODE = 6; - private static final int GCM_MODE = 7; + static final int GCM_MODE = 7; /* * variables used for performing the GCM (key+iv) uniqueness check. @@ -196,7 +196,7 @@ final class CipherCore { cipher = new CounterMode(rawImpl); unitBytes = 1; padding = null; - } else if (modeUpperCase.startsWith("GCM")) { + } else if (modeUpperCase.equals("GCM")) { // can only be used for block ciphers w/ 128-bit block size if (blockSize != 16) { throw new NoSuchAlgorithmException @@ -223,6 +223,15 @@ final class CipherCore { } } + /** + * Returns the mode of this cipher. + * + * @return the parsed cipher mode + */ + int getMode() { + return cipherMode; + } + private static int getNumOfUnit(String mode, int offset, int blockSize) throws NoSuchAlgorithmException { int result = blockSize; // use blockSize as default value diff --git a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index df98d9318622ee21fc57cf2c0e6b5197721e0c82..e4edbf061f3edced8b1eb8a9a9a203eb9ba1aa10 100644 --- a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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,6 +49,16 @@ final class GaloisCounterMode extends FeedbackCipher { static int DEFAULT_TAG_LEN = AES_BLOCK_SIZE; static int DEFAULT_IV_LEN = 12; // in bytes + // In NIST SP 800-38D, GCM input size is limited to be no longer + // than (2^36 - 32) bytes. Otherwise, the counter will wrap + // around and lead to a leak of plaintext. + // However, given the current GCM spec requirement that recovered + // text can only be returned after successful tag verification, + // we are bound by limiting the data size to the size limit of + // java byte array, e.g. Integer.MAX_VALUE, since all data + // can only be returned by the doFinal(...) call. + private static final int MAX_BUF_SIZE = Integer.MAX_VALUE; + // buffer for AAD data; if null, meaning update has been called private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); private int sizeOfAAD = 0; @@ -89,9 +99,13 @@ final class GaloisCounterMode extends FeedbackCipher { } } - // ivLen in bits - private static byte[] getLengthBlock(int ivLen) { + private static byte[] getLengthBlock(int ivLenInBytes) { + long ivLen = ((long)ivLenInBytes) << 3; byte[] out = new byte[AES_BLOCK_SIZE]; + out[8] = (byte)(ivLen >>> 56); + out[9] = (byte)(ivLen >>> 48); + out[10] = (byte)(ivLen >>> 40); + out[11] = (byte)(ivLen >>> 32); out[12] = (byte)(ivLen >>> 24); out[13] = (byte)(ivLen >>> 16); out[14] = (byte)(ivLen >>> 8); @@ -99,13 +113,22 @@ final class GaloisCounterMode extends FeedbackCipher { return out; } - // aLen and cLen both in bits - private static byte[] getLengthBlock(int aLen, int cLen) { + private static byte[] getLengthBlock(int aLenInBytes, int cLenInBytes) { + long aLen = ((long)aLenInBytes) << 3; + long cLen = ((long)cLenInBytes) << 3; byte[] out = new byte[AES_BLOCK_SIZE]; + out[0] = (byte)(aLen >>> 56); + out[1] = (byte)(aLen >>> 48); + out[2] = (byte)(aLen >>> 40); + out[3] = (byte)(aLen >>> 32); out[4] = (byte)(aLen >>> 24); out[5] = (byte)(aLen >>> 16); out[6] = (byte)(aLen >>> 8); out[7] = (byte)aLen; + out[8] = (byte)(cLen >>> 56); + out[9] = (byte)(cLen >>> 48); + out[10] = (byte)(cLen >>> 40); + out[11] = (byte)(cLen >>> 32); out[12] = (byte)(cLen >>> 24); out[13] = (byte)(cLen >>> 16); out[14] = (byte)(cLen >>> 8); @@ -142,13 +165,20 @@ final class GaloisCounterMode extends FeedbackCipher { } else { g.update(iv); } - byte[] lengthBlock = getLengthBlock(iv.length*8); + byte[] lengthBlock = getLengthBlock(iv.length); g.update(lengthBlock); j0 = g.digest(); } return j0; } + private static void checkDataLength(int processed, int len) { + if (processed > MAX_BUF_SIZE - len) { + throw new ProviderException("SunJCE provider only supports " + + "input size up to " + MAX_BUF_SIZE + " bytes"); + } + } + GaloisCounterMode(SymmetricCipher embeddedCipher) { super(embeddedCipher); aadBuffer = new ByteArrayOutputStream(); @@ -319,20 +349,22 @@ final class GaloisCounterMode extends FeedbackCipher { // Feed the AAD data to GHASH, pad if necessary void processAAD() { - if (aadBuffer != null && aadBuffer.size() > 0) { - byte[] aad = aadBuffer.toByteArray(); - sizeOfAAD = aad.length; - aadBuffer = null; - - int lastLen = aad.length % AES_BLOCK_SIZE; - if (lastLen != 0) { - ghashAllToS.update(aad, 0, aad.length - lastLen); - byte[] padded = expandToOneBlock(aad, aad.length - lastLen, - lastLen); - ghashAllToS.update(padded); - } else { - ghashAllToS.update(aad); + if (aadBuffer != null) { + if (aadBuffer.size() > 0) { + byte[] aad = aadBuffer.toByteArray(); + sizeOfAAD = aad.length; + + int lastLen = aad.length % AES_BLOCK_SIZE; + if (lastLen != 0) { + ghashAllToS.update(aad, 0, aad.length - lastLen); + byte[] padded = expandToOneBlock(aad, aad.length - lastLen, + lastLen); + ghashAllToS.update(padded); + } else { + ghashAllToS.update(aad); + } } + aadBuffer = null; } } @@ -386,6 +418,8 @@ final class GaloisCounterMode extends FeedbackCipher { * @param outOfs the offset in out */ int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { + checkDataLength(processed, len); + processAAD(); if (len > 0) { gctrPAndC.update(in, inOfs, len, out, outOfs); @@ -410,17 +444,23 @@ final class GaloisCounterMode extends FeedbackCipher { */ int encryptFinal(byte[] in, int inOfs, int len, byte[] out, int outOfs) throws IllegalBlockSizeException, ShortBufferException { + if (len > MAX_BUF_SIZE - tagLenBytes) { + throw new ShortBufferException + ("Can't fit both data and tag into one buffer"); + } if (out.length - outOfs < (len + tagLenBytes)) { throw new ShortBufferException("Output buffer too small"); } + checkDataLength(processed, len); + processAAD(); if (len > 0) { doLastBlock(in, inOfs, len, out, outOfs, true); } byte[] lengthBlock = - getLengthBlock(sizeOfAAD*8, processed*8); + getLengthBlock(sizeOfAAD, processed); ghashAllToS.update(lengthBlock); byte[] s = ghashAllToS.digest(); byte[] sOut = new byte[s.length]; @@ -454,6 +494,8 @@ final class GaloisCounterMode extends FeedbackCipher { * @param outOfs the offset in out */ int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { + checkDataLength(ibuffer.size(), len); + processAAD(); if (len > 0) { @@ -488,10 +530,21 @@ final class GaloisCounterMode extends FeedbackCipher { if (len < tagLenBytes) { throw new AEADBadTagException("Input too short - need tag"); } + // do this check here can also catch the potential integer overflow + // scenario for the subsequent output buffer capacity check. + checkDataLength(ibuffer.size(), (len - tagLenBytes)); + if (out.length - outOfs < ((ibuffer.size() + len) - tagLenBytes)) { throw new ShortBufferException("Output buffer too small"); } + processAAD(); + + // get the trailing tag bytes from 'in' + byte[] tag = new byte[tagLenBytes]; + System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes); + len -= tagLenBytes; + if (len != 0) { ibuffer.write(in, inOfs, len); } @@ -502,17 +555,12 @@ final class GaloisCounterMode extends FeedbackCipher { len = in.length; ibuffer.reset(); - byte[] tag = new byte[tagLenBytes]; - // get the trailing tag bytes from 'in' - System.arraycopy(in, len - tagLenBytes, tag, 0, tagLenBytes); - len -= tagLenBytes; - if (len > 0) { doLastBlock(in, inOfs, len, out, outOfs, false); } byte[] lengthBlock = - getLengthBlock(sizeOfAAD*8, processed*8); + getLengthBlock(sizeOfAAD, processed); ghashAllToS.update(lengthBlock); byte[] s = ghashAllToS.digest(); diff --git a/src/share/classes/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java b/src/share/classes/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java index 4961ac6286a67530202452b6b57602be1ee4b8b5..141a332c61c678e8faa63228c36b6b2a7b79b668 100644 --- a/src/share/classes/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java +++ b/src/share/classes/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java @@ -81,7 +81,7 @@ public class JMXSubjectDomainCombiner extends SubjectDomainCombiner { * A ProtectionDomain with a null CodeSource and an empty permission set. */ private static final ProtectionDomain pdNoPerms = - new ProtectionDomain(nullCodeSource, new Permissions()); + new ProtectionDomain(nullCodeSource, new Permissions(), null, null); /** * Get the current AccessControlContext combined with the supplied subject. diff --git a/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/share/classes/java/lang/invoke/DirectMethodHandle.java index cabd0716341678ae1b0fbe9f8471669e2d09c8e9..df3c2be141952fc9fc76d9069884d444333a7344 100644 --- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -158,7 +158,7 @@ class DirectMethodHandle extends MethodHandle { private static LambdaForm preparedLambdaForm(MemberName m) { assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead MethodType mtype = m.getInvocationType().basicType(); - assert(!m.isMethodHandleInvoke() || "invokeBasic".equals(m.getName())) : m; + assert(!m.isMethodHandleInvoke()) : m; int which; switch (m.getReferenceKind()) { case REF_invokeVirtual: which = LF_INVVIRTUAL; break; diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java index 09a742f55ec01069cbc5bac896c9aca36275c330..9420d3b042e847c7e238d141cdcc46d6daf4f8d2 100644 --- a/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/share/classes/java/lang/invoke/LambdaForm.java @@ -1034,7 +1034,7 @@ class LambdaForm { this.member = member; this.resolvedHandle = resolvedHandle; // The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest. - //assert(!isInvokeBasic()); + //assert(!isInvokeBasic(member)); } NamedFunction(MethodType basicInvokerType) { assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType; @@ -1045,13 +1045,13 @@ class LambdaForm { // necessary to pass BigArityTest this.member = Invokers.invokeBasicMethod(basicInvokerType); } - assert(isInvokeBasic()); + assert(isInvokeBasic(member)); } - private boolean isInvokeBasic() { + private static boolean isInvokeBasic(MemberName member) { return member != null && - member.isMethodHandleInvoke() && - "invokeBasic".equals(member.getName()); + member.getDeclaringClass() == MethodHandle.class && + "invokeBasic".equals(member.getName()); } // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc. @@ -1191,7 +1191,7 @@ class LambdaForm { assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype)) : Arrays.asList(mh, rtype, arity); MemberName member = mh.internalMemberName(); - if (member != null && member.getName().equals("invokeBasic") && member.isMethodHandleInvoke()) { + if (isInvokeBasic(member)) { assert(arity > 0); assert(a[0] instanceof MethodHandle); MethodHandle mh2 = (MethodHandle) a[0]; diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java index bcc08e71d912373b3d0aecd408c86de8c7cc5040..b2fc757390e8df67231b8783d48de96911d57370 100644 --- a/src/share/classes/java/lang/invoke/MemberName.java +++ b/src/share/classes/java/lang/invoke/MemberName.java @@ -341,7 +341,6 @@ import java.util.Objects; } /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). - * Also returns true for the non-public MH.invokeBasic. */ public boolean isMethodHandleInvoke() { final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; @@ -356,7 +355,6 @@ import java.util.Objects; switch (name) { case "invoke": case "invokeExact": - case "invokeBasic": // internal sig-poly method return true; default: return false; diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index 85118904818e28d50d6ed615b3ca4987697457a4..4e8494a19b03e117a52d0d82b81e2bd9352514dd 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -864,8 +864,6 @@ assertEquals("", (String) MH_newString.invokeExact()); return invoker(type); if ("invokeExact".equals(name)) return exactInvoker(type); - if ("invokeBasic".equals(name)) - return basicInvoker(type); assert(!MemberName.isMethodHandleInvokeName(name)); return null; } diff --git a/src/share/classes/java/security/ProtectionDomain.java b/src/share/classes/java/security/ProtectionDomain.java index b1778490f5a6dacc18e2250ff5e9999472bf5f7c..ffd2def18d108dcbd33819f34ea5cf70d90e6ad4 100644 --- a/src/share/classes/java/security/ProtectionDomain.java +++ b/src/share/classes/java/security/ProtectionDomain.java @@ -475,6 +475,11 @@ public class ProtectionDomain { } }; } + + @Override + public boolean getStaticPermissionsField(ProtectionDomain pd) { + return pd.staticPermissions; + } }); } } diff --git a/src/share/classes/javax/security/auth/SubjectDomainCombiner.java b/src/share/classes/javax/security/auth/SubjectDomainCombiner.java index da75d68342506ca3be7584b41d79a70c08b79199..89812d28476dfda6ca221a09c24db9f5c9df7388 100644 --- a/src/share/classes/javax/security/auth/SubjectDomainCombiner.java +++ b/src/share/classes/javax/security/auth/SubjectDomainCombiner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ import java.security.Security; import java.util.Set; import java.util.WeakHashMap; import java.lang.ref.WeakReference; +import sun.misc.SharedSecrets; +import sun.misc.JavaSecurityProtectionDomainAccess; /** * A {@code SubjectDomainCombiner} updates ProtectionDomains @@ -65,6 +67,9 @@ public class SubjectDomainCombiner implements java.security.DomainCombiner { private static final boolean allowCaching = (useJavaxPolicy && cachePolicy()); + private static final JavaSecurityProtectionDomainAccess pdAccess = + SharedSecrets.getJavaSecurityProtectionDomainAccess(); + /** * Associate the provided {@code Subject} with this * {@code SubjectDomainCombiner}. @@ -239,10 +244,16 @@ public class SubjectDomainCombiner implements java.security.DomainCombiner { subjectPd = cachedPDs.getValue(pd); if (subjectPd == null) { - subjectPd = new ProtectionDomain(pd.getCodeSource(), + if (pdAccess.getStaticPermissionsField(pd)) { + // Need to keep static ProtectionDomain objects static + subjectPd = new ProtectionDomain(pd.getCodeSource(), + pd.getPermissions()); + } else { + subjectPd = new ProtectionDomain(pd.getCodeSource(), pd.getPermissions(), pd.getClassLoader(), principals); + } cachedPDs.putValue(pd, subjectPd); } else { allNew = false; @@ -341,60 +352,63 @@ public class SubjectDomainCombiner implements java.security.DomainCombiner { ProtectionDomain subjectPd = cachedPDs.getValue(pd); if (subjectPd == null) { - - // XXX - // we must first add the original permissions. - // that way when we later add the new JAAS permissions, - // any unresolved JAAS-related permissions will - // automatically get resolved. - - // get the original perms - Permissions perms = new Permissions(); - PermissionCollection coll = pd.getPermissions(); - java.util.Enumeration e; - if (coll != null) { - synchronized (coll) { - e = coll.elements(); - while (e.hasMoreElements()) { - Permission newPerm = + if (pdAccess.getStaticPermissionsField(pd)) { + // keep static ProtectionDomain objects static + subjectPd = new ProtectionDomain(pd.getCodeSource(), + pd.getPermissions()); + } else { + // XXX + // we must first add the original permissions. + // that way when we later add the new JAAS permissions, + // any unresolved JAAS-related permissions will + // automatically get resolved. + + // get the original perms + Permissions perms = new Permissions(); + PermissionCollection coll = pd.getPermissions(); + java.util.Enumeration e; + if (coll != null) { + synchronized (coll) { + e = coll.elements(); + while (e.hasMoreElements()) { + Permission newPerm = e.nextElement(); - perms.add(newPerm); + perms.add(newPerm); + } } } - } - // get perms from the policy - - final java.security.CodeSource finalCs = pd.getCodeSource(); - final Subject finalS = subject; - PermissionCollection newPerms = - java.security.AccessController.doPrivileged - (new PrivilegedAction() { - @SuppressWarnings("deprecation") - public PermissionCollection run() { - return - javax.security.auth.Policy.getPolicy().getPermissions - (finalS, finalCs); - } - }); - - // add the newly granted perms, - // avoiding duplicates - synchronized (newPerms) { - e = newPerms.elements(); - while (e.hasMoreElements()) { - Permission newPerm = e.nextElement(); - if (!perms.implies(newPerm)) { - perms.add(newPerm); - if (debug != null) - debug.println ( - "Adding perm " + newPerm + "\n"); + // get perms from the policy + final java.security.CodeSource finalCs = pd.getCodeSource(); + final Subject finalS = subject; + PermissionCollection newPerms = + java.security.AccessController.doPrivileged + (new PrivilegedAction() { + @SuppressWarnings("deprecation") + public PermissionCollection run() { + return + javax.security.auth.Policy.getPolicy().getPermissions + (finalS, finalCs); + } + }); + + // add the newly granted perms, + // avoiding duplicates + synchronized (newPerms) { + e = newPerms.elements(); + while (e.hasMoreElements()) { + Permission newPerm = e.nextElement(); + if (!perms.implies(newPerm)) { + perms.add(newPerm); + if (debug != null) + debug.println ( + "Adding perm " + newPerm + "\n"); + } } } + subjectPd = new ProtectionDomain + (finalCs, perms, pd.getClassLoader(), principals); } - subjectPd = new ProtectionDomain - (finalCs, perms, pd.getClassLoader(), principals); - if (allowCaching) cachedPDs.putValue(pd, subjectPd); } diff --git a/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java b/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java index 95560ffab68210ca69a5ddc299b80e2780dc0204..3567f350f23cbc47ddfd5335840d702828db78a8 100644 --- a/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java +++ b/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java @@ -36,4 +36,9 @@ public interface JavaSecurityProtectionDomainAccess { * Returns the ProtectionDomainCache. */ ProtectionDomainCache getProtectionDomainCache(); + + /** + * Returns the staticPermissions field of the specified object + */ + boolean getStaticPermissionsField(ProtectionDomain pd); } diff --git a/src/windows/classes/sun/nio/ch/PipeImpl.java b/src/windows/classes/sun/nio/ch/PipeImpl.java index b86580dccadc7d2713ca56fc4392c9710b778c59..d1052cf6489707a4cd0d84ee4c2f6fb3212fc46c 100644 --- a/src/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/windows/classes/sun/nio/ch/PipeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.nio.channels.spi.*; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; +import java.security.SecureRandom; import java.util.Random; @@ -47,24 +48,16 @@ import java.util.Random; class PipeImpl extends Pipe { + // Number of bytes in the secret handshake. + private static final int NUM_SECRET_BYTES = 16; + + // Random object for handshake values + private static final Random RANDOM_NUMBER_GENERATOR = new SecureRandom(); // Source and sink channels private SourceChannel source; private SinkChannel sink; - // Random object for handshake values - private static final Random rnd; - - static { - byte[] someBytes = new byte[8]; - boolean resultOK = IOUtil.randomBytes(someBytes); - if (resultOK) { - rnd = new Random(ByteBuffer.wrap(someBytes).getLong()); - } else { - rnd = new Random(); - } - } - private class Initializer implements PrivilegedExceptionAction { @@ -112,6 +105,10 @@ class PipeImpl SocketChannel sc2 = null; try { + // Create secret with a backing array. + ByteBuffer secret = ByteBuffer.allocate(NUM_SECRET_BYTES); + ByteBuffer bb = ByteBuffer.allocate(NUM_SECRET_BYTES); + // Loopback address InetAddress lb = InetAddress.getByName("127.0.0.1"); assert(lb.isLoopbackAddress()); @@ -128,18 +125,22 @@ class PipeImpl // Establish connection (assume connections are eagerly // accepted) sc1 = SocketChannel.open(sa); - ByteBuffer bb = ByteBuffer.allocate(8); - long secret = rnd.nextLong(); - bb.putLong(secret).flip(); - sc1.write(bb); + RANDOM_NUMBER_GENERATOR.nextBytes(secret.array()); + do { + sc1.write(secret); + } while (secret.hasRemaining()); + secret.rewind(); // Get a connection and verify it is legitimate sc2 = ssc.accept(); - bb.clear(); - sc2.read(bb); + do { + sc2.read(bb); + } while (bb.hasRemaining()); bb.rewind(); - if (bb.getLong() == secret) + + if (bb.equals(secret)) break; + sc2.close(); sc1.close(); } diff --git a/src/windows/native/sun/windows/awt_Font.cpp b/src/windows/native/sun/windows/awt_Font.cpp index a3d59656297d920d18f3d2e5784ac4c3fb2de206..76bdd84ffdd08d03468d68591173456e6702bbf9 100644 --- a/src/windows/native/sun/windows/awt_Font.cpp +++ b/src/windows/native/sun/windows/awt_Font.cpp @@ -256,7 +256,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) AwtFont* awtFont = NULL; jobjectArray compFont = NULL; - int cfnum; + int cfnum = 0; try { if (env->EnsureLocalCapacity(3) < 0) @@ -264,7 +264,9 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) if (IsMultiFont(env, font)) { compFont = GetComponentFonts(env, font); - cfnum = env->GetArrayLength(compFont); + if (compFont != NULL) { + cfnum = env->GetArrayLength(compFont); + } } else { compFont = NULL; cfnum = 0; @@ -614,7 +616,9 @@ int AwtFont::getFontDescriptorNumber(JNIEnv *env, jobject font, if (IsMultiFont(env, font)) { array = GetComponentFonts(env, font); - num = env->GetArrayLength(array); + if (array != NULL) { + num = env->GetArrayLength(array); + } } else { array = NULL; num = 0; @@ -672,14 +676,16 @@ SIZE AwtFont::DrawStringSize_sub(jstring str, HDC hDC, if (IsMultiFont(env, font)) { jobject peer = env->CallObjectMethod(font, AwtFont::peerMID); - array = (jobjectArray)(env->CallObjectMethod( - peer, AwtFont::makeConvertedMultiFontStringMID, str)); - DASSERT(!safe_ExceptionOccurred(env)); + if (peer != NULL) { + array = (jobjectArray)(env->CallObjectMethod( + peer, AwtFont::makeConvertedMultiFontStringMID, str)); + DASSERT(!safe_ExceptionOccurred(env)); - if (array != NULL) { - arrayLength = env->GetArrayLength(array); + if (array != NULL) { + arrayLength = env->GetArrayLength(array); + } + env->DeleteLocalRef(peer); } - env->DeleteLocalRef(peer); } else { array = NULL; arrayLength = 0; diff --git a/src/windows/native/sun/windows/awt_Font.h b/src/windows/native/sun/windows/awt_Font.h index 83df5e7fba21c609f70a57043b1314dbb891c889..3f4d8e6a67db624c8a2a4b3aaf5c4d69a5fdf1c9 100644 --- a/src/windows/native/sun/windows/awt_Font.h +++ b/src/windows/native/sun/windows/awt_Font.h @@ -230,11 +230,14 @@ public: INLINE static jobjectArray GetComponentFonts(JNIEnv *env, jobject font) { jobject platformFont = env->CallObjectMethod(font, AwtFont::peerMID); - jobjectArray result = - (jobjectArray)(env->GetObjectField(platformFont, - AwtFont::componentFontsID)); - env->DeleteLocalRef(platformFont); - return result; + if (platformFont != NULL) { + jobjectArray result = + (jobjectArray)(env->GetObjectField(platformFont, + AwtFont::componentFontsID)); + env->DeleteLocalRef(platformFont); + return result; + } + return NULL; } /*