--- old/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java 2015-07-02 17:26:50.222759590 +0200 +++ new/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java 2015-07-02 17:26:49.790759570 +0200 @@ -27,6 +27,9 @@ import java.security.InvalidKeyException; import java.security.ProviderException; +import java.util.Objects; + +import jdk.internal.HotSpotIntrinsicCandidate; /** @@ -138,15 +141,22 @@ * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + byte[] cipher, int cipherOffset) { + cryptBlockSizeCheck(plainLen); + cryptNullAndBoundsCheck(plain, plainOffset, plainLen); + cryptNullAndBoundsCheck(cipher, cipherOffset, plainLen); + return implEncrypt(plain, plainOffset, plainLen, + cipher, cipherOffset); + } + + @HotSpotIntrinsicCandidate + private int implEncrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { - if ((plainLen % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; - plainOffset+=blockSize, cipherOffset += blockSize) { + plainOffset += blockSize, cipherOffset += blockSize) { for (int i = 0; i < blockSize; i++) { k[i] = (byte)(plain[i + plainOffset] ^ r[i]); } @@ -179,11 +189,17 @@ * @return the length of the decrypted data */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) + byte[] plain, int plainOffset) { + cryptBlockSizeCheck(cipherLen); + cryptNullAndBoundsCheck(cipher, cipherOffset, cipherLen); + cryptNullAndBoundsCheck(plain, plainOffset, cipherLen); + return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + } + + @HotSpotIntrinsicCandidate + private int implDecrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { - if ((cipherLen % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } int endIndex = cipherOffset + cipherLen; for (; cipherOffset < endIndex; @@ -196,4 +212,27 @@ } 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) { + if (len <= 0) { + return; // not an error because cryptImpl/decryptImpl won't execute if len <= 0 + } + + 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); + } + } }