From c08a2e2281a46b45a2a4977350f1584e1f2252c8 Mon Sep 17 00:00:00 2001 From: akosarev Date: Fri, 17 Jun 2016 12:59:14 +0000 Subject: [PATCH] 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 --- .../com/sun/crypto/provider/CipherCore.java | 67 +++++++++++-------- .../provider/Cipher/AES/TestCopySafe.java | 6 +- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/share/classes/com/sun/crypto/provider/CipherCore.java b/src/share/classes/com/sun/crypto/provider/CipherCore.java index 408da3057..d99cf39b7 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 @@ -720,6 +720,15 @@ final class CipherCore { 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 @@ final class CipherCore { 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. + 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; + } + // process 'buffer' if (decrypting) { - outLen = cipher.decrypt(input, inputOffset, len, output, outputOffset); + outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset); } else { - outLen = cipher.encrypt(input, inputOffset, len, output, outputOffset); - } - 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; - } - if (inConsumed != 0) { - System.arraycopy(input, inputOffset, in, len - inConsumed, inConsumed); - inputOffset += inConsumed; - inputLen -= inConsumed; + outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset); } + outputOffset += outLen; + buffered = 0; + } + if (inputConsumed > 0) { // still has input to process if (decrypting) { - outLen = cipher.decrypt(in, 0, len, output, outputOffset); + outLen += cipher.decrypt(input, inputOffset, inputConsumed, + output, outputOffset); } else { - outLen = cipher.encrypt(in, 0, len, output, outputOffset); + outLen += cipher.encrypt(input, inputOffset, inputConsumed, + output, outputOffset); } + inputOffset += inputConsumed; + inputLen -= inputConsumed; } } // Let's keep track of how many bytes are needed to make @@ -925,8 +934,10 @@ final class CipherCore { 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; } diff --git a/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java b/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java index 20dff835f..697da6750 100644 --- a/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java +++ b/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java @@ -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 @@ public class TestCopySafe { 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", -- GitLab