8027575: b113 causing a lot of memory allocation and regression for wls_webapp_atomics
Summary: Reduce buffer allocation and do multiple cipher encryption/decryption calls.
Reviewed-by: xuelei, ascarpino
--- a/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java Tue Jul 01 20:35:30 2014 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/CipherCore.java Tue Jul 01 20:35:43 2014 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, 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
@@ -720,6 +720,15 @@
int outLen = 0;
if (len != 0) { // there is some work to do
+ if ((input == output)
+ && (outputOffset < (inputOffset + inputLen))
+ && (inputOffset < (outputOffset + buffer.length))) {
+ // copy 'input' out to avoid its content being
+ // overwritten prematurely.
+ input = Arrays.copyOfRange(input, inputOffset,
+ inputOffset + inputLen);
+ inputOffset = 0;
+ }
if (len <= buffered) {
// all to-be-processed data are from 'buffer'
if (decrypting) {
@@ -732,37 +741,37 @@
System.arraycopy(buffer, len, buffer, 0, buffered);
}
} else { // len > buffered
- if ((input != output) && (buffered == 0)) {
- // all to-be-processed data are from 'input'
- // however, note that if 'input' and 'output' are the same,
- // then they can't be passed directly to the underlying cipher
- // engine operations as data may be overwritten before they
- // are read.
- if (decrypting) {
- outLen = cipher.decrypt(input, inputOffset, len, output, outputOffset);
- } else {
- outLen = cipher.encrypt(input, inputOffset, len, output, outputOffset);
+ int inputConsumed = len - buffered;
+ int temp;
+ if (buffered > 0) {
+ int bufferCapacity = buffer.length - buffered;
+ if (bufferCapacity != 0) {
+ temp = Math.min(bufferCapacity, inputConsumed);
+ System.arraycopy(input, inputOffset, buffer, buffered, temp);
+ inputOffset += temp;
+ inputConsumed -= temp;
+ inputLen -= temp;
+ buffered += temp;
}
- inputOffset += len;
- inputLen -= len;
- } else {
- // assemble the data using both 'buffer' and 'input'
- byte[] in = new byte[len];
- int inConsumed = len - buffered;
- if (buffered != 0) {
- System.arraycopy(buffer, 0, in, 0, buffered);
- buffered = 0;
+ // process 'buffer'
+ if (decrypting) {
+ outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset);
+ } else {
+ outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
}
- if (inConsumed != 0) {
- System.arraycopy(input, inputOffset, in, len - inConsumed, inConsumed);
- inputOffset += inConsumed;
- inputLen -= inConsumed;
+ outputOffset += outLen;
+ buffered = 0;
+ }
+ if (inputConsumed > 0) { // still has input to process
+ if (decrypting) {
+ outLen += cipher.decrypt(input, inputOffset, inputConsumed,
+ output, outputOffset);
+ } else {
+ outLen += cipher.encrypt(input, inputOffset, inputConsumed,
+ output, outputOffset);
}
- if (decrypting) {
- outLen = cipher.decrypt(in, 0, len, output, outputOffset);
- } else {
- outLen = cipher.encrypt(in, 0, len, output, outputOffset);
- }
+ inputOffset += inputConsumed;
+ inputLen -= inputConsumed;
}
}
// Let's keep track of how many bytes are needed to make
@@ -925,8 +934,10 @@
byte[] finalBuf = input;
int finalOffset = inputOffset;
int finalBufLen = inputLen;
- if ((input == output) || (buffered != 0) ||
- (!decrypting && padding != null)) {
+ if ((buffered != 0) || (!decrypting && padding != null) ||
+ ((input == output)
+ && (outputOffset < (inputOffset + inputLen))
+ && (inputOffset < (outputOffset + buffer.length)))) {
if (decrypting || padding == null) {
paddingLen = 0;
}
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java Tue Jul 01 20:35:30 2014 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java Tue Jul 01 20:35:43 2014 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8026943
+ * @bug 8026943 8027575
* @summary Verify that same buffer can be used as input and output when
* using Cipher objects.
* @author Valerie Peng
@@ -44,7 +44,7 @@
private static SecretKey KEY = new SecretKeySpec(new byte[16], "AES");
private static byte[] IV = new byte[16];
- private static int[] OFFSETS = { 1, 8, 17 };
+ private static int[] OFFSETS = { 1, 8, 9, 16, 17, 32, 33 };
private static final String[] MODES = {
"ECB", "CBC", "PCBC", "CTR", "CTS",