diff --git a/src/share/classes/com/sun/crypto/provider/AESCrypt.java b/src/share/classes/com/sun/crypto/provider/AESCrypt.java index 0adb07092e5f6482cb4d4aacda5d4ecb58652038..c74f609f3ad4a32ab144b673edbbe8916d14389f 100644 --- a/src/share/classes/com/sun/crypto/provider/AESCrypt.java +++ b/src/share/classes/com/sun/crypto/provider/AESCrypt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -38,7 +38,6 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.MessageDigest; -import java.util.Objects; /** * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit @@ -348,8 +347,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants */ void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) { - cryptBlockCheck(in, inOffset); - cryptBlockCheck(out, outOffset); + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. implEncryptBlock(in, inOffset, out, outOffset); } @@ -426,8 +425,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants */ void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) { - cryptBlockCheck(in, inOffset); - cryptBlockCheck(out, outOffset); + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. implDecryptBlock(in, inOffset, out, outOffset); } @@ -588,26 +587,6 @@ final class AESCrypt extends SymmetricCipher implements AESConstants out[outOffset ] = (byte)(Si[(a0 ) & 0xFF] ^ (t1 )); } - // Used to perform all checks required by the Java semantics - // (i.e., null checks and bounds checks) on the input parameters - // to encryptBlock and to decryptBlock. - // Normally, the Java Runtime performs these checks, however, as - // encryptBlock and decryptBlock are possibly replaced with - // compiler intrinsics, the JDK performs the required checks instead. - // Does not check accesses to class-internal (private) arrays. - private static void cryptBlockCheck(byte[] array, int offset) { - Objects.requireNonNull(array); - - if (offset < 0 || offset >= array.length) { - throw new ArrayIndexOutOfBoundsException(offset); - } - - int largestIndex = offset + AES_BLOCK_SIZE - 1; - if (largestIndex < 0 || largestIndex >= array.length) { - throw new ArrayIndexOutOfBoundsException(largestIndex); - } - } - /** * Expand a user-supplied key material into a session key. * diff --git a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java index 0f8040fe20cf0ad74bdc7631a14eec15904260fc..7fdc6e1f67b22162a4b99afdbeef6a7822aabdfa 100644 --- a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java +++ b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -29,6 +29,7 @@ import java.security.InvalidKeyException; import java.security.ProviderException; import java.util.Objects; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in cipher block chaining (CBC) mode. @@ -143,9 +144,9 @@ class CipherBlockChaining extends FeedbackCipher { if (plainLen <= 0) { return plainLen; } - cryptBlockSizeCheck(plainLen); - cryptNullAndBoundsCheck(plain, plainOffset, plainLen); - cryptNullAndBoundsCheck(cipher, cipherOffset, plainLen); + ArrayUtil.blockSizeCheck(plainLen, blockSize); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen); return implEncrypt(plain, plainOffset, plainLen, cipher, cipherOffset); } @@ -193,9 +194,9 @@ class CipherBlockChaining extends FeedbackCipher { if (cipherLen <= 0) { return cipherLen; } - cryptBlockSizeCheck(cipherLen); - cryptNullAndBoundsCheck(cipher, cipherOffset, cipherLen); - cryptNullAndBoundsCheck(plain, plainOffset, cipherLen); + ArrayUtil.blockSizeCheck(cipherLen, blockSize); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen); return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } @@ -214,23 +215,4 @@ class CipherBlockChaining extends FeedbackCipher { } return cipherLen; } - - private void cryptBlockSizeCheck(int len) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } - } - - private static void cryptNullAndBoundsCheck(byte[] array, int offset, int len) { - Objects.requireNonNull(array); - - if (offset < 0 || offset >= array.length) { - throw new ArrayIndexOutOfBoundsException(offset); - } - - int endIndex = offset + len - 1; - if (endIndex < 0 || endIndex >= array.length) { - throw new ArrayIndexOutOfBoundsException(endIndex); - } - } } diff --git a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java index 84b527efe5b03afb2e7177b3c65b0b91deed4ae9..71e94cc7ffaee5ac1c7648e51e4025dbe6751cf6 100644 --- a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java +++ b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,6 +27,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.ProviderException; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in cipher-feedback (CFB) mode. @@ -149,9 +150,9 @@ final class CipherFeedback extends FeedbackCipher { */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { - if ((plainLen % numBytes) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(plainLen, numBytes); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen); int nShift = blockSize - numBytes; int loopCount = plainLen / numBytes; @@ -225,9 +226,10 @@ final class CipherFeedback extends FeedbackCipher { */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { - if ((cipherLen % numBytes) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + + ArrayUtil.blockSizeCheck(cipherLen, numBytes); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen); int nShift = blockSize - numBytes; int loopCount = cipherLen / numBytes; diff --git a/src/share/classes/com/sun/crypto/provider/CounterMode.java b/src/share/classes/com/sun/crypto/provider/CounterMode.java index b810b8ff8c7611701fcf8d6fea45779635c8d8e2..cda5db2cf8505053fdc9707101627c06f90cf8d5 100644 --- a/src/share/classes/com/sun/crypto/provider/CounterMode.java +++ b/src/share/classes/com/sun/crypto/provider/CounterMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -27,6 +27,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in counter (CTR) mode. @@ -173,6 +174,10 @@ final class CounterMode extends FeedbackCipher { if (len == 0) { return 0; } + + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); + int result = len; while (len-- > 0) { if (used >= blockSize) { diff --git a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java index 334e4245e27a5522000c75b10ea06f1bb2c558b5..24e85adb9ba888ba5471a7a5ccc311f821e7d659 100644 --- a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java +++ b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,6 +27,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.ProviderException; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in electronic codebook (ECB) mode. @@ -112,9 +113,10 @@ final class ElectronicCodeBook extends FeedbackCipher { * @return the length of the encrypted data */ int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(len, blockSize); + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.encryptBlock(in, inOff, out, outOff); inOff += blockSize; @@ -141,9 +143,10 @@ final class ElectronicCodeBook extends FeedbackCipher { * @return the length of the decrypted data */ int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(len, blockSize); + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.decryptBlock(in, inOff, out, outOff); inOff += blockSize; diff --git a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index cdb22d1217919c632e1b427289382c6899163337..b574848704c44a8b972a56d9433054e16d346560 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, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,6 +30,8 @@ import java.io.*; import java.security.*; import javax.crypto.*; import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; +import sun.security.util.ArrayUtil; + /** * This class represents ciphers in GaloisCounter (GCM) mode. @@ -406,8 +408,8 @@ final class GaloisCounterMode extends FeedbackCipher { /** * Performs encryption operation. * - *
The input plain text in
, starting at inOff
- * and ending at (inOff + len - 1)
, is encrypted. The result
+ *
The input plain text The exception formatter accepts two arguments: a {@code String}
+ * describing the out-of-bounds range check that failed, referred to as the
+ * check kind; and a {@code List Three check kinds are supported {@code checkIndex},
+ * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
+ * respectively to the specified application of an exception formatter as an
+ * argument to the out-of-bounds range check methods
+ * {@link #checkIndex(int, int, BiFunction) checkIndex},
+ * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
+ * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
+ * Thus a supported check kind corresponds to a method name and the
+ * out-of-bound integer values correspond to method argument values, in
+ * order, preceding the exception formatter argument (similar in many
+ * respects to the form of arguments required for a reflective invocation of
+ * such a range check method).
+ *
+ * Formatter arguments conforming to such supported check kinds will
+ * produce specific exception messages describing failed out-of-bounds
+ * checks. Otherwise, more generic exception messages will be produced in
+ * any of the following cases: the check kind is supported but fewer
+ * or more out-of-bounds values are supplied, the check kind is not
+ * supported, the check kind is {@code null}, or the list of out-of-bound
+ * values is {@code null}.
+ *
+ * @apiNote
+ * This method produces an out-of-bounds exception formatter that can be
+ * passed as an argument to any of the supported out-of-bounds range check
+ * methods declared by {@code Objects}. For example, a formatter producing
+ * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
+ * {@code static final} field as follows:
+ * If the {@code index} is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkIndex};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code index} and {@code length}.
+ *
+ * @param The sub-range is defined to be out-of-bounds if any of the following
+ * inequalities is true:
+ * If the sub-range is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkFromToIndex};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
+ *
+ * @param The sub-range is defined to be out-of-bounds if any of the following
+ * inequalities is true:
+ * If the sub-range is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkFromIndexSize};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code fromIndex}, {@code size}, and
+ * {@code length}.
+ *
+ * @param in
, starting at inOfs
+ * and ending at (inOfs + len - 1)
, is encrypted. The result
* is stored in out
, starting at outOfs
.
*
* @param in the buffer with the input data to be encrypted
@@ -422,15 +424,18 @@ final class GaloisCounterMode extends FeedbackCipher {
int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
checkDataLength(processed, len);
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(len, blockSize);
processAAD();
+
if (len > 0) {
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+ ArrayUtil.nullAndBoundsCheck(out, outOfs, len);
+
gctrPAndC.update(in, inOfs, len, out, outOfs);
processed += len;
ghashAllToS.update(out, outOfs, len);
}
+
return len;
}
@@ -450,7 +455,10 @@ final class GaloisCounterMode extends FeedbackCipher {
throw new ShortBufferException
("Can't fit both data and tag into one buffer");
}
- if (out.length - outOfs < (len + tagLenBytes)) {
+ try {
+ ArrayUtil.nullAndBoundsCheck(out, outOfs,
+ (len + tagLenBytes));
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
@@ -458,6 +466,8 @@ final class GaloisCounterMode extends FeedbackCipher {
processAAD();
if (len > 0) {
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+
doLastBlock(in, inOfs, len, out, outOfs, true);
}
@@ -493,15 +503,14 @@ final class GaloisCounterMode extends FeedbackCipher {
int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
checkDataLength(ibuffer.size(), len);
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(len, blockSize);
processAAD();
if (len > 0) {
// store internally until decryptFinal is called because
// spec mentioned that only return recovered data after tag
// is successfully verified
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
ibuffer.write(in, inOfs, len);
}
return 0;
@@ -530,22 +539,28 @@ 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)) {
+ try {
+ ArrayUtil.nullAndBoundsCheck(out, outOfs,
+ (ibuffer.size() + len) - tagLenBytes);
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
processAAD();
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+
// 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) {
+ if (len > 0) {
ibuffer.write(in, inOfs, len);
}
diff --git a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
index 47d9d63c93df6efbfa5a9e69a506193a5f210de4..7b518836cd1cfe0c37705acf347218a8a8e3cf89 100644
--- a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
+++ b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
+import sun.security.util.ArrayUtil;
/**
* This class represents ciphers in output-feedback (OFB) mode.
@@ -148,10 +149,10 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ ArrayUtil.blockSizeCheck(plainLen, numBytes);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
- if ((plainLen % numBytes) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
int nShift = blockSize - numBytes;
int loopCount = plainLen / numBytes;
@@ -189,6 +190,9 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encryptFinal(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int oddBytes = plainLen % numBytes;
int len = encrypt(plain, plainOffset, (plainLen - oddBytes),
cipher, cipherOffset);
diff --git a/src/share/classes/com/sun/crypto/provider/PCBC.java b/src/share/classes/com/sun/crypto/provider/PCBC.java
index fd99bb0cbd51208bc0c9d152df59d0e8fa59beaf..544776ec04fe07d25602708370297221bcbecec5 100644
--- a/src/share/classes/com/sun/crypto/provider/PCBC.java
+++ b/src/share/classes/com/sun/crypto/provider/PCBC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
+import sun.security.util.ArrayUtil;
/**
@@ -136,9 +137,10 @@ final class PCBC extends FeedbackCipher {
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset)
{
- if ((plainLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(plainLen, blockSize);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int i;
int endIndex = plainOffset + plainLen;
@@ -176,9 +178,10 @@ final class PCBC extends FeedbackCipher {
int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
byte[] plain, int plainOffset)
{
- if ((cipherLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(cipherLen, blockSize);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen);
+
int i;
int endIndex = cipherOffset + cipherLen;
diff --git a/src/share/classes/jdk/internal/util/Preconditions.java b/src/share/classes/jdk/internal/util/Preconditions.java
new file mode 100644
index 0000000000000000000000000000000000000000..5be620d28a27fb9e7b4506a57387904cfa636554
--- /dev/null
+++ b/src/share/classes/jdk/internal/util/Preconditions.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 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
+ * 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.util;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Utility methods to check if state or arguments are correct.
+ *
+ */
+public class Preconditions {
+
+ /**
+ * Maps out-of-bounds values to a runtime exception.
+ *
+ * @param checkKind the kind of bounds check, whose name may correspond
+ * to the name of one of the range check methods, checkIndex,
+ * checkFromToIndex, checkFromIndexSize
+ * @param args the out-of-bounds arguments that failed the range check.
+ * If the checkKind corresponds a the name of a range check method
+ * then the bounds arguments are those that can be passed in order
+ * to the method.
+ * @param oobef the exception formatter that when applied with a checkKind
+ * and a list out-of-bounds arguments returns a runtime exception.
+ * If {@code null} then, it is as if an exception formatter was
+ * supplied that returns {@link IndexOutOfBoundsException} for any
+ * given arguments.
+ * @return the runtime exception
+ */
+ private static RuntimeException outOfBounds(
+ BiFunction{@code
+ * static final
+ * BiFunction
+ * The formatter instance {@code AIOOBEF} may be passed as an argument to an
+ * out-of-bounds range check method, such as checking if an {@code index}
+ * is within the bounds of a {@code limit}:
+ * {@code
+ * checkIndex(index, limit, AIOOBEF);
+ * }
+ * If the bounds check fails then the range check method will throw an
+ * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
+ * message that is a produced from {@code AIOOBEF} as follows:
+ * {@code
+ * AIOOBEF.apply("checkIndex", List.of(index, limit));
+ * }
+ *
+ * @param f the exception factory, that produces an exception from a message
+ * where the message is produced and formatted by the returned
+ * exception formatter. If this factory is stateless and side-effect
+ * free then so is the returned formatter.
+ * Exceptions thrown by the factory are relayed to the caller
+ * of the returned formatter.
+ * @param
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *