# HG changeset patch # User andrew # Date 1586146198 -3600 # Mon Apr 06 05:09:58 2020 +0100 # Node ID 812f64a9a671d03141abbed30d99c3cbe08de5a5 # Parent 2f1b1489f97fa43ed73957e485ace89cb5960dcc # Parent b3db2cd0d9c4b1f7c51d90ff1fc4c13ac3305f4a Merge jdk8u252-b09 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1210,3 +1210,4 @@ 8b6bfe415412e6be732f7c7e616b689b6a55e6c7 aarch64-shenandoah-jdk8u252-b07 e17fe591a374d25725b077f5e99a87de6eb2ab5b jdk8u252-b08 c38803f8a50bf2f949d5b8288bc2243da3803928 aarch64-shenandoah-jdk8u252-b08 +3ad9fa6a5a13fab2188de93bdaa38c1a7f8f5521 jdk8u252-b09 diff --git a/make/CompileLaunchers.gmk b/make/CompileLaunchers.gmk --- a/make/CompileLaunchers.gmk +++ b/make/CompileLaunchers.gmk @@ -163,7 +163,6 @@ -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \ -DPROGNAME='"$1"' $(DPACKAGEPATH) \ $2, \ - CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \ LDFLAGS := $(LDFLAGS_JDKEXE) \ $(ORIGIN_ARG) \ diff --git a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java --- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java +++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java @@ -81,6 +81,12 @@ private static final class SecretKeyEntry { Date date; // the creation date of this entry SealedObject sealedKey; + + // Maximum possible length of sealedKey. Used to detect malicious + // input data. This field is set to the file length of the keystore + // at loading. It is useless when creating a new SecretKeyEntry + // to be store in a keystore. + int maxLength; } // Trusted certificate @@ -136,8 +142,8 @@ } key = keyProtector.recover(encrInfo); } else { - key = - keyProtector.unseal(((SecretKeyEntry)entry).sealedKey); + SecretKeyEntry ske = ((SecretKeyEntry)entry); + key = keyProtector.unseal(ske.sealedKey, ske.maxLength); } return key; @@ -282,6 +288,7 @@ // seal and store the key entry.sealedKey = keyProtector.seal(key); + entry.maxLength = Integer.MAX_VALUE; entries.put(alias.toLowerCase(Locale.ENGLISH), entry); } @@ -691,6 +698,10 @@ if (stream == null) return; + byte[] allData = IOUtils.readAllBytes(stream); + int fullLength = allData.length; + + stream = new ByteArrayInputStream(allData); if (password != null) { md = getPreKeyedHash(password); dis = new DataInputStream(new DigestInputStream(stream, md)); @@ -829,10 +840,11 @@ AccessController.doPrivileged( (PrivilegedAction)() -> { ObjectInputFilter.Config.setObjectInputFilter( - ois2, new DeserializationChecker()); + ois2, new DeserializationChecker(fullLength)); return null; }); entry.sealedKey = (SealedObject)ois.readObject(); + entry.maxLength = fullLength; // NOTE: don't close ois here since we are still // using dis!!! } catch (ClassNotFoundException cnfe) { @@ -909,8 +921,17 @@ * deserialized. */ private static class DeserializationChecker implements ObjectInputFilter { + private static final int MAX_NESTED_DEPTH = 2; + // Full length of keystore, anything inside a SecretKeyEntry should not + // be bigger. Otherwise, must be illegal. + private final int fullLength; + + public DeserializationChecker(int fullLength) { + this.fullLength = fullLength; + } + @Override public ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo info) { @@ -919,6 +940,7 @@ long nestedDepth = info.depth(); if ((nestedDepth == 1 && info.serialClass() != SealedObjectForKeyProtector.class) || + info.arrayLength() > fullLength || (nestedDepth > MAX_NESTED_DEPTH && info.serialClass() != null && info.serialClass() != Object.class)) { diff --git a/src/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/share/classes/com/sun/crypto/provider/KeyProtector.java --- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java +++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -352,8 +352,11 @@ /** * Unseals the sealed key. + * + * @param maxLength Maximum possible length of so. + * If bigger, must be illegal. */ - Key unseal(SealedObject so) + Key unseal(SealedObject so, int maxLength) throws NoSuchAlgorithmException, UnrecoverableKeyException { SecretKey sKey = null; try { @@ -388,7 +391,7 @@ SunJCE.getInstance(), "PBEWithMD5AndTripleDES"); cipher.init(Cipher.DECRYPT_MODE, sKey, params); - return soForKeyProtector.getKey(cipher); + return soForKeyProtector.getKey(cipher, maxLength); } catch (NoSuchAlgorithmException ex) { // Note: this catch needed to be here because of the // later catch of GeneralSecurityException diff --git a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java --- a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java +++ b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java @@ -73,7 +73,7 @@ return params; } - final Key getKey(Cipher c) + final Key getKey(Cipher c, int maxLength) throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { @@ -82,7 +82,7 @@ AccessController.doPrivileged( (PrivilegedAction) () -> { ObjectInputFilter.Config.setObjectInputFilter(ois, - DeserializationChecker.ONE_FILTER); + new DeserializationChecker(maxLength)); return null; }); try { @@ -110,7 +110,7 @@ */ private static class DeserializationChecker implements ObjectInputFilter { - private static final ObjectInputFilter ONE_FILTER; + private static final ObjectInputFilter OWN_FILTER; static { String prop = AccessController.doPrivileged( @@ -122,26 +122,32 @@ return Security.getProperty(KEY_SERIAL_FILTER); } }); - ONE_FILTER = new DeserializationChecker(prop == null ? null - : ObjectInputFilter.Config.createFilter(prop)); + OWN_FILTER = prop == null + ? null + : ObjectInputFilter.Config.createFilter(prop); } - private final ObjectInputFilter base; + // Maximum possible length of anything inside + private final int maxLength; - private DeserializationChecker(ObjectInputFilter base) { - this.base = base; + private DeserializationChecker(int maxLength) { + this.maxLength = maxLength; } @Override public ObjectInputFilter.Status checkInput( ObjectInputFilter.FilterInfo info) { + if (info.arrayLength() > maxLength) { + return Status.REJECTED; + } + if (info.serialClass() == Object.class) { return Status.UNDECIDED; } - if (base != null) { - Status result = base.checkInput(info); + if (OWN_FILTER != null) { + Status result = OWN_FILTER.checkInput(info); if (result != Status.UNDECIDED) { return result; } diff --git a/src/share/classes/com/sun/net/httpserver/Headers.java b/src/share/classes/com/sun/net/httpserver/Headers.java --- a/src/share/classes/com/sun/net/httpserver/Headers.java +++ b/src/share/classes/com/sun/net/httpserver/Headers.java @@ -80,11 +80,14 @@ char[] b = key.toCharArray(); if (b[0] >= 'a' && b[0] <= 'z') { b[0] = (char)(b[0] - ('a' - 'A')); - } + } else if (b[0] == '\r' || b[0] == '\n') + throw new IllegalArgumentException("illegal character in key"); + for (int i=1; i= 'A' && b[i] <= 'Z') { b[i] = (char) (b[i] + ('a' - 'A')); - } + } else if (b[i] == '\r' || b[i] == '\n') + throw new IllegalArgumentException("illegal character in key"); } return new String(b); } @@ -126,6 +129,8 @@ } public List put(String key, List value) { + for (String v : value) + checkValue(v); return map.put (normalize(key), value); } @@ -137,6 +142,7 @@ * @param value the header value to add to the header */ public void add (String key, String value) { + checkValue(value); String k = normalize(key); List l = map.get(k); if (l == null) { @@ -146,6 +152,30 @@ l.add (value); } + private static void checkValue(String value) { + int len = value.length(); + for (int i=0; i= len - 2) { + throw new IllegalArgumentException("Illegal CR found in header"); + } + char c1 = value.charAt(i+1); + char c2 = value.charAt(i+2); + if (c1 != '\n') { + throw new IllegalArgumentException("Illegal char found after CR in header"); + } + if (c2 != ' ' && c2 != '\t') { + throw new IllegalArgumentException("No whitespace found after CRLF in header"); + } + i+=2; + } else if (c == '\n') { + throw new IllegalArgumentException("Illegal LF found in header"); + } + } + } + /** * sets the given value as the sole header value * for the given key. If the mapping does not diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java --- a/src/share/classes/java/io/ObjectInputStream.java +++ b/src/share/classes/java/io/ObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, 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 @@ -1797,6 +1797,8 @@ break; case TC_REFERENCE: descriptor = (ObjectStreamClass) readHandle(unshared); + // Should only reference initialized class descriptors + descriptor.checkInitialized(); break; case TC_PROXYCLASSDESC: descriptor = readProxyDesc(unshared); diff --git a/src/share/classes/java/io/ObjectStreamClass.java b/src/share/classes/java/io/ObjectStreamClass.java --- a/src/share/classes/java/io/ObjectStreamClass.java +++ b/src/share/classes/java/io/ObjectStreamClass.java @@ -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 @@ -864,6 +864,17 @@ } /** + * Throws InvalidClassException if not initialized. + * To be called in cases where an uninitialized class descriptor indicates + * a problem in the serialization stream. + */ + final void checkInitialized() throws InvalidClassException { + if (!initialized) { + throw new InvalidClassException("Class descriptor should be initialized"); + } + } + + /** * Throws an InvalidClassException if object instances referencing this * class descriptor should not be allowed to deserialize. This method does * not apply to deserialization of enum constants. @@ -1119,6 +1130,9 @@ } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed throw new InternalError(ex); + } catch (InstantiationError err) { + throw (InstantiationException) + new InstantiationException().initCause(err); } } else { throw new UnsupportedOperationException(); diff --git a/src/share/classes/java/lang/instrument/package.html b/src/share/classes/java/lang/instrument/package.html --- a/src/share/classes/java/lang/instrument/package.html +++ b/src/share/classes/java/lang/instrument/package.html @@ -38,6 +38,13 @@ Provides services that allow Java programming language agents to instrument programs running on the JVM. The mechanism for instrumentation is modification of the byte-codes of methods. +

+Note: developers/admininstrators are responsible for verifying the trustworthiness of +content and structure of the Java Agents they deploy, since those are able to arbitrarily +transform the bytecode from other JAR files. Since that happens after the Jars containing +the bytecode have been verified as trusted, the trustworthiness of a Java Agent can determine +the trust towards the entire program. +

Package Specification

diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java --- a/src/share/classes/java/lang/invoke/MethodType.java +++ b/src/share/classes/java/lang/invoke/MethodType.java @@ -97,7 +97,8 @@ // The remaining fields are caches of various sorts: private @Stable MethodTypeForm form; // erased form, plus cached data about primitives - private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version + private @Stable Object wrapAlt; // alternative wrapped/unwrapped version and + // private communication for readObject and readResolve private @Stable Invokers invokers; // cache of handy higher-order adapters private @Stable String methodDescriptor; // cache for toMethodDescriptorString @@ -673,7 +674,7 @@ private static MethodType wrapWithPrims(MethodType pt) { assert(pt.hasPrimitives()); - MethodType wt = pt.wrapAlt; + MethodType wt = (MethodType)pt.wrapAlt; if (wt == null) { // fill in lazily wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP); @@ -685,7 +686,7 @@ private static MethodType unwrapWithNoPrims(MethodType wt) { assert(!wt.hasPrimitives()); - MethodType uwt = wt.wrapAlt; + MethodType uwt = (MethodType)wt.wrapAlt; if (uwt == null) { // fill in lazily uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP); @@ -1144,27 +1145,18 @@ * @see #writeObject */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - // Assign temporary defaults in case this object escapes - MethodType_init(void.class, NO_PTYPES); + // Assign defaults in case this object escapes + UNSAFE.putObject(this, rtypeOffset, void.class); + UNSAFE.putObject(this, ptypesOffset, NO_PTYPES); s.defaultReadObject(); // requires serialPersistentFields to be an empty array Class returnType = (Class) s.readObject(); Class[] parameterArray = (Class[]) s.readObject(); - parameterArray = parameterArray.clone(); // make sure it is unshared - // Assign deserialized values - MethodType_init(returnType, parameterArray); - } - - // Initialization of state for deserialization only - private void MethodType_init(Class rtype, Class[] ptypes) { - // In order to communicate these values to readResolve, we must - // store them into the implementation-specific final fields. - checkRtype(rtype); - checkPtypes(ptypes); - UNSAFE.putObject(this, rtypeOffset, rtype); - UNSAFE.putObject(this, ptypesOffset, ptypes); + // Verify all operands, and make sure ptypes is unshared + // Cache the new MethodType for readResolve + wrapAlt = new MethodType[]{MethodType.methodType(returnType, parameterArray)}; } // Support for resetting final fields while deserializing @@ -1189,12 +1181,10 @@ // Do not use a trusted path for deserialization: // return makeImpl(rtype, ptypes, true); // Verify all operands, and make sure ptypes is unshared: - try { - return methodType(rtype, ptypes); - } finally { - // Re-assign defaults in case this object escapes - MethodType_init(void.class, NO_PTYPES); - } + // Return a new validated MethodType for the rtype and ptypes passed from readObject. + MethodType mt = ((MethodType[])wrapAlt)[0]; + wrapAlt = null; + return mt; } /** diff --git a/src/share/classes/java/math/MutableBigInteger.java b/src/share/classes/java/math/MutableBigInteger.java --- a/src/share/classes/java/math/MutableBigInteger.java +++ b/src/share/classes/java/math/MutableBigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -2088,8 +2088,8 @@ } /** - * Calculate the multiplicative inverse of this mod mod, where mod is odd. - * This and mod are not changed by the calculation. + * Calculate the multiplicative inverse of this modulo mod, where the mod + * argument is odd. This and mod are not changed by the calculation. * * This method implements an algorithm due to Richard Schroeppel, that uses * the same intermediate representation as Montgomery Reduction @@ -2143,8 +2143,18 @@ k += trailingZeros; } - while (c.sign < 0) - c.signedAdd(p); + if (c.compare(p) >= 0) { // c has a larger magnitude than p + MutableBigInteger remainder = c.divide(p, + new MutableBigInteger()); + // The previous line ignores the sign so we copy the data back + // into c which will restore the sign as needed (and converts + // it back to a SignedMutableBigInteger) + c.copyValue(remainder); + } + + if (c.sign < 0) { + c.signedAdd(p); + } return fixup(c, p, k); } @@ -2182,8 +2192,8 @@ } // In theory, c may be greater than p at this point (Very rare!) - while (c.compare(p) >= 0) - c.subtract(p); + if (c.compare(p) >= 0) + c = c.divide(p, new MutableBigInteger()); return c; } diff --git a/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template b/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template --- a/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template +++ b/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template @@ -72,7 +72,6 @@ public $Type$Buffer slice() { int pos = this.position(); int lim = this.limit(); - assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); int off = (pos << $LG_BYTES_PER_VALUE$) + offset; assert (off >= 0); diff --git a/src/share/classes/java/nio/Direct-X-Buffer.java.template b/src/share/classes/java/nio/Direct-X-Buffer.java.template --- a/src/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/share/classes/java/nio/Direct-X-Buffer.java.template @@ -206,7 +206,6 @@ public $Type$Buffer slice() { int pos = this.position(); int lim = this.limit(); - assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); int off = (pos << $LG_BYTES_PER_VALUE$); assert (off >= 0); diff --git a/src/share/classes/java/nio/Heap-X-Buffer.java.template b/src/share/classes/java/nio/Heap-X-Buffer.java.template --- a/src/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/src/share/classes/java/nio/Heap-X-Buffer.java.template @@ -95,12 +95,15 @@ } public $Type$Buffer slice() { + int pos = this.position(); + int lim = this.limit(); + int rem = (pos <= lim ? lim - pos : 0); return new Heap$Type$Buffer$RW$(hb, -1, 0, - this.remaining(), - this.remaining(), - this.position() + offset); + rem, + rem, + pos + offset); } public $Type$Buffer duplicate() { @@ -147,10 +150,11 @@ public $Type$Buffer get($type$[] dst, int offset, int length) { checkBounds(offset, length, dst.length); - if (length > remaining()) + int pos = position(); + if (length > limit() - pos) throw new BufferUnderflowException(); - System.arraycopy(hb, ix(position()), dst, offset, length); - position(position() + length); + System.arraycopy(hb, ix(pos), dst, offset, length); + position(pos + length); return this; } @@ -185,10 +189,11 @@ public $Type$Buffer put($type$[] src, int offset, int length) { #if[rw] checkBounds(offset, length, src.length); - if (length > remaining()) + int pos = position(); + if (length > limit() - pos) throw new BufferOverflowException(); - System.arraycopy(src, offset, hb, ix(position()), length); - position(position() + length); + System.arraycopy(src, offset, hb, ix(pos), length); + position(pos + length); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -201,19 +206,22 @@ if (src == this) throw new IllegalArgumentException(); Heap$Type$Buffer sb = (Heap$Type$Buffer)src; - int n = sb.remaining(); - if (n > remaining()) + int pos = position(); + int sbpos = sb.position(); + int n = sb.limit() - sbpos; + if (n > limit() - pos) throw new BufferOverflowException(); - System.arraycopy(sb.hb, sb.ix(sb.position()), - hb, ix(position()), n); - sb.position(sb.position() + n); - position(position() + n); + System.arraycopy(sb.hb, sb.ix(sbpos), + hb, ix(pos), n); + sb.position(sbpos + n); + position(pos + n); } else if (src.isDirect()) { int n = src.remaining(); - if (n > remaining()) + int pos = position(); + if (n > limit() - pos) throw new BufferOverflowException(); - src.get(hb, ix(position()), n); - position(position() + n); + src.get(hb, ix(pos), n); + position(pos + n); } else { super.put(src); } @@ -225,8 +233,10 @@ public $Type$Buffer compact() { #if[rw] - System.arraycopy(hb, ix(position()), hb, ix(0), remaining()); - position(remaining()); + int pos = position(); + int rem = limit() - pos; + System.arraycopy(hb, ix(pos), hb, ix(0), rem); + position(rem); limit(capacity()); discardMark(); return this; @@ -284,8 +294,9 @@ } public CharBuffer asCharBuffer() { - int size = this.remaining() >> 1; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 1; + int off = offset + pos; return (bigEndian ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this, -1, @@ -335,8 +346,9 @@ } public ShortBuffer asShortBuffer() { - int size = this.remaining() >> 1; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 1; + int off = offset + pos; return (bigEndian ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this, -1, @@ -386,8 +398,9 @@ } public IntBuffer asIntBuffer() { - int size = this.remaining() >> 2; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 2; + int off = offset + pos; return (bigEndian ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this, -1, @@ -437,8 +450,9 @@ } public LongBuffer asLongBuffer() { - int size = this.remaining() >> 3; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 3; + int off = offset + pos; return (bigEndian ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this, -1, @@ -488,8 +502,9 @@ } public FloatBuffer asFloatBuffer() { - int size = this.remaining() >> 2; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 2; + int off = offset + pos; return (bigEndian ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this, -1, @@ -539,8 +554,9 @@ } public DoubleBuffer asDoubleBuffer() { - int size = this.remaining() >> 3; - int off = offset + position(); + int pos = position(); + int size = (limit() - pos) >> 3; + int off = offset + pos; return (bigEndian ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this, -1, diff --git a/src/share/classes/java/nio/StringCharBuffer.java b/src/share/classes/java/nio/StringCharBuffer.java --- a/src/share/classes/java/nio/StringCharBuffer.java +++ b/src/share/classes/java/nio/StringCharBuffer.java @@ -42,12 +42,15 @@ } public CharBuffer slice() { + int pos = this.position(); + int lim = this.limit(); + int rem = (pos <= lim ? lim - pos : 0); return new StringCharBuffer(str, -1, 0, - this.remaining(), - this.remaining(), - offset + this.position()); + rem, + rem, + offset + pos); } private StringCharBuffer(CharSequence s, diff --git a/src/share/classes/java/util/Scanner.java b/src/share/classes/java/util/Scanner.java --- a/src/share/classes/java/util/Scanner.java +++ b/src/share/classes/java/util/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -425,7 +425,7 @@ // here but what can we do? The final authority will be // whatever parse method is invoked, so ultimately the // Scanner will do the right thing - String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})"; + String digit = "((?i)["+radixDigits+"\\p{javaDigit}])"; String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+ groupSeparator+digit+digit+digit+")+)"; // digit++ is the possessive form which is necessary for reducing @@ -475,7 +475,7 @@ private Pattern decimalPattern; private void buildFloatAndDecimalPattern() { // \\p{javaDigit} may not be perfect, see above - String digit = "([0-9]|(\\p{javaDigit}))"; + String digit = "(([0-9\\p{javaDigit}]))"; String exponent = "([eE][+-]?"+digit+"+)?"; String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+ groupSeparator+digit+digit+digit+")+)"; @@ -1188,25 +1188,25 @@ // These must be literalized to avoid collision with regex // metacharacters such as dot or parenthesis - groupSeparator = "\\" + dfs.getGroupingSeparator(); - decimalSeparator = "\\" + dfs.getDecimalSeparator(); + groupSeparator = "\\x{" + Integer.toHexString(dfs.getGroupingSeparator()) + "}"; + decimalSeparator = "\\x{" + Integer.toHexString(dfs.getDecimalSeparator()) + "}"; // Quoting the nonzero length locale-specific things // to avoid potential conflict with metacharacters - nanString = "\\Q" + dfs.getNaN() + "\\E"; - infinityString = "\\Q" + dfs.getInfinity() + "\\E"; + nanString = Pattern.quote(dfs.getNaN()); + infinityString = Pattern.quote(dfs.getInfinity()); positivePrefix = df.getPositivePrefix(); if (positivePrefix.length() > 0) - positivePrefix = "\\Q" + positivePrefix + "\\E"; + positivePrefix = Pattern.quote(positivePrefix); negativePrefix = df.getNegativePrefix(); if (negativePrefix.length() > 0) - negativePrefix = "\\Q" + negativePrefix + "\\E"; + negativePrefix = Pattern.quote(negativePrefix); positiveSuffix = df.getPositiveSuffix(); if (positiveSuffix.length() > 0) - positiveSuffix = "\\Q" + positiveSuffix + "\\E"; + positiveSuffix = Pattern.quote(positiveSuffix); negativeSuffix = df.getNegativeSuffix(); if (negativeSuffix.length() > 0) - negativeSuffix = "\\Q" + negativeSuffix + "\\E"; + negativeSuffix = Pattern.quote(negativeSuffix); // Force rebuilding and recompilation of locale dependent // primitive patterns diff --git a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java --- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java @@ -153,9 +153,15 @@ "support DOM Level 2 and be namespace aware"); } if (tag.equals("KeyInfo")) { - return new DOMKeyInfo(element, new UnmarshalContext(), getProvider()); + try { + return new DOMKeyInfo(element, new UnmarshalContext(), getProvider()); + } catch (MarshalException me) { + throw me; + } catch (Exception e) { + throw new MarshalException(e); + } } else { - throw new MarshalException("invalid KeyInfo tag: " + tag); + throw new MarshalException("Invalid KeyInfo tag: " + tag); } } diff --git a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java --- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java @@ -190,9 +190,15 @@ "support DOM Level 2 and be namespace aware"); } if (tag.equals("Signature")) { - return new DOMXMLSignature(element, context, getProvider()); + try { + return new DOMXMLSignature(element, context, getProvider()); + } catch (MarshalException me) { + throw me; + } catch (Exception e) { + throw new MarshalException(e); + } } else { - throw new MarshalException("invalid Signature tag: " + tag); + throw new MarshalException("Invalid Signature tag: " + tag); } } diff --git a/src/share/classes/sun/security/rsa/RSAKeyFactory.java b/src/share/classes/sun/security/rsa/RSAKeyFactory.java --- a/src/share/classes/sun/security/rsa/RSAKeyFactory.java +++ b/src/share/classes/sun/security/rsa/RSAKeyFactory.java @@ -115,6 +115,9 @@ * Used by RSASignature and RSACipher. */ public static RSAKey toRSAKey(Key key) throws InvalidKeyException { + if (key == null) { + throw new InvalidKeyException("Key must not be null"); + } if ((key instanceof RSAPrivateKeyImpl) || (key instanceof RSAPrivateCrtKeyImpl) || (key instanceof RSAPublicKeyImpl)) { diff --git a/src/share/classes/sun/security/ssl/ClientHandshaker.java b/src/share/classes/sun/security/ssl/ClientHandshaker.java --- a/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1337,7 +1337,7 @@ @Override HandshakeMessage getKickstartMessage() throws SSLException { // session ID of the ClientHello message - SessionId sessionId = SSLSessionImpl.nullSession.getSessionId(); + SessionId sessionId = new SessionId(new byte[0]); // a list of cipher suites sent by the client CipherSuiteList cipherSuites = getActiveCipherSuites(); diff --git a/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/share/classes/sun/security/ssl/SSLEngineImpl.java --- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -375,7 +375,7 @@ } sslContext = ctx; - sess = SSLSessionImpl.nullSession; + sess = new SSLSessionImpl(); handshakeSession = null; /* diff --git a/src/share/classes/sun/security/ssl/SSLSessionImpl.java b/src/share/classes/sun/security/ssl/SSLSessionImpl.java --- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -73,11 +73,6 @@ */ final class SSLSessionImpl extends ExtendedSSLSession { - /* - * we only really need a single null session - */ - static final SSLSessionImpl nullSession = new SSLSessionImpl(); - // compression methods private static final byte compression_null = 0; @@ -148,7 +143,7 @@ * be used either by a client or by a server, as a connection is * first opened and before handshaking begins. */ - private SSLSessionImpl() { + SSLSessionImpl() { this(ProtocolVersion.NONE, CipherSuite.C_NULL, null, new SessionId(false, null), null, -1, false, null); } @@ -657,14 +652,6 @@ */ @Override synchronized public void invalidate() { - // - // Can't invalidate the NULL session -- this would be - // attempted when we get a handshaking error on a brand - // new connection, with no "real" session yet. - // - if (this == nullSession) { - return; - } invalidated = true; if (debug != null && Debug.isOn("session")) { System.out.println("%% Invalidated: " + this); diff --git a/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/share/classes/sun/security/ssl/SSLSocketImpl.java --- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -610,7 +610,7 @@ */ private void init(SSLContextImpl context, boolean isServer) { sslContext = context; - sess = SSLSessionImpl.nullSession; + sess = new SSLSessionImpl(); handshakeSession = null; /* diff --git a/src/share/instrument/InvocationAdapter.c b/src/share/instrument/InvocationAdapter.c --- a/src/share/instrument/InvocationAdapter.c +++ b/src/share/instrument/InvocationAdapter.c @@ -203,6 +203,17 @@ */ oldLen = (int)strlen(premainClass); newLen = modifiedUtf8LengthOfUtf8(premainClass, oldLen); + /* + * According to JVMS class name is represented as CONSTANT_Utf8_info, + * so its length is u2 (i.e. must be <= 0xFFFF). + */ + if (newLen > 0xFFFF) { + fprintf(stderr, "-javaagent: Premain-Class value is too big\n"); + free(jarfile); + if (options != NULL) free(options); + freeAttributes(attributes); + return JNI_ERR; + } if (newLen == oldLen) { premainClass = strdup(premainClass); } else { @@ -362,6 +373,17 @@ */ oldLen = strlen(agentClass); newLen = modifiedUtf8LengthOfUtf8(agentClass, oldLen); + /* + * According to JVMS class name is represented as CONSTANT_Utf8_info, + * so its length is u2 (i.e. must be <= 0xFFFF). + */ + if (newLen > 0xFFFF) { + fprintf(stderr, "Agent-Class value is too big\n"); + free(jarfile); + if (options != NULL) free(options); + freeAttributes(attributes); + return AGENT_ERROR_BADJAR; + } if (newLen == oldLen) { agentClass = strdup(agentClass); } else { diff --git a/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.c b/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.c --- a/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.c +++ b/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.c @@ -206,7 +206,7 @@ int depthBytes = format->depthBytes; pRect->pBits = pBits; - INCPN(byte_t, pRect->pBits, y * stride + x * depthBytes); + INCPN(byte_t, pRect->pBits, (intptr_t) y * stride + x * depthBytes); pRect->numLines = height; pRect->numSamples = width; pRect->stride = stride * jump; diff --git a/src/share/native/sun/security/ec/impl/mpi.c b/src/share/native/sun/security/ec/impl/mpi.c --- a/src/share/native/sun/security/ec/impl/mpi.c +++ b/src/share/native/sun/security/ec/impl/mpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ * Netscape Communications Corporation * Douglas Stebila of Sun Laboratories. * - * Last Modified Date from the Original Code: June 2014 + * Last Modified Date from the Original Code: Nov 2019 *********************************************************************** */ /* Arbitrary precision integer arithmetic library */ @@ -2134,7 +2134,10 @@ } } if (res >= 0) { - while (MP_SIGN(c) != MP_ZPOS) { + if (s_mp_cmp(c, p) >= 0) { + MP_CHECKOK( mp_div(c, p, NULL, c)); + } + if (MP_SIGN(c) != MP_ZPOS) { MP_CHECKOK( mp_add(c, p, c) ); } res = k; diff --git a/src/solaris/native/sun/awt/multiVis.c b/src/solaris/native/sun/awt/multiVis.c --- a/src/solaris/native/sun/awt/multiVis.c +++ b/src/solaris/native/sun/awt/multiVis.c @@ -401,7 +401,7 @@ ximage = XCreateImage(disp,fakeVis,(uint32_t) depth,format,0,NULL, (uint32_t)width,(uint32_t)height,8,0); - ximage->data = calloc(ximage->bytes_per_line*height*((format==ZPixmap)? 1 : depth), sizeof(char)); + ximage->data = calloc((size_t) ximage->bytes_per_line*height*((format==ZPixmap)? 1 : depth), sizeof(char)); ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/ for (reg = (image_region_type *) first_in_list( regions); reg; diff --git a/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c b/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c --- a/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c +++ b/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c @@ -263,7 +263,7 @@ return; } dstScan = image->bytes_per_line; - image->data = malloc(dstScan * height); + image->data = malloc((size_t) dstScan * height); if (image->data == NULL) { XFree(image); AWT_UNLOCK(); diff --git a/src/solaris/native/sun/java2d/x11/X11TextRenderer_md.c b/src/solaris/native/sun/java2d/x11/X11TextRenderer_md.c --- a/src/solaris/native/sun/java2d/x11/X11TextRenderer_md.c +++ b/src/solaris/native/sun/java2d/x11/X11TextRenderer_md.c @@ -154,7 +154,7 @@ height = bottom - top; top -= clipTop; left -= clipLeft; - pPix = ((jubyte *) theImage->data) + (left >> 3) + top * scan; + pPix = ((jubyte *) theImage->data) + (left >> 3) + (intptr_t) top * scan; left &= 0x07; if (theImage->bitmap_bit_order == MSBFirst) { left = 0x80 >> left; diff --git a/src/solaris/native/sun/java2d/x11/XRBackendNative.c b/src/solaris/native/sun/java2d/x11/XRBackendNative.c --- a/src/solaris/native/sun/java2d/x11/XRBackendNative.c +++ b/src/solaris/native/sun/java2d/x11/XRBackendNative.c @@ -756,7 +756,7 @@ if (ea != 1.0f) { for (line=0; line < height; line++) { for (pix=0; pix < width; pix++) { - int index = maskScan*line + pix + maskOff; + size_t index = (size_t) maskScan * line + pix + maskOff; mask[index] = (((unsigned char) mask[index])*ea); } } @@ -781,8 +781,8 @@ if (imageFits) { for (line=0; line < height; line++) { for (pix=0; pix < width; pix++) { - img->data[line*img->bytes_per_line + pix] = - (unsigned char) (mask[maskScan*line + pix + maskOff]); + img->data[(size_t) line * img->bytes_per_line + pix] = + (unsigned char) (mask[(size_t) maskScan * line + pix + maskOff]); } } } else { diff --git a/test/java/math/BigInteger/ModInvTime.java b/test/java/math/BigInteger/ModInvTime.java new file mode 100644 --- /dev/null +++ b/test/java/math/BigInteger/ModInvTime.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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 + * 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 8225603 + * @summary Tests whether modInverse() completes in a reasonable time + * @run main/othervm ModInvTime + */ +import java.math.BigInteger; + +public class ModInvTime { + public static void main(String[] args) throws InterruptedException { + BigInteger prime = new BigInteger("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643"); + BigInteger s = new BigInteger("9552729729729327851382626410162104591956625415831952158766936536163093322096473638446154604799898109762512409920799"); + System.out.format("int length: %d, modulus length: %d%n", + s.bitLength(), prime.bitLength()); + + System.out.println("Computing modular inverse ..."); + BigInteger mi = s.modInverse(prime); + System.out.format("Modular inverse: %s%n", mi); + check(s, prime, mi); + + BigInteger ns = s.negate(); + BigInteger nmi = ns.modInverse(prime); + System.out.format("Modular inverse of negation: %s%n", nmi); + check(ns, prime, nmi); + } + + public static void check(BigInteger val, BigInteger mod, BigInteger inv) { + BigInteger r = inv.multiply(val).remainder(mod); + if (r.signum() == -1) + r = r.add(mod); + if (!r.equals(BigInteger.ONE)) + throw new RuntimeException("Numerically incorrect modular inverse"); + } +}