changeset 10238:c2e818a8d678

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
author valeriep
date Tue, 01 Jul 2014 20:35:43 +0000
parents 44b89a35be6e
children 1a5a2a5d7505
files src/share/classes/com/sun/crypto/provider/CipherCore.java test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java
diffstat 2 files changed, 44 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java	Tue Jul 01 20:35:30 2014 +0000
+++ b/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.
+                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);
+                         outLen = cipher.encrypt(buffer, 0, buffered, 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;
+                    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 (inConsumed != 0) {
-                        System.arraycopy(input, inputOffset, in, len - inConsumed, inConsumed);
-                        inputOffset += inConsumed;
-                        inputLen -= inConsumed;
-                    }
-                    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/test/com/sun/crypto/provider/Cipher/AES/TestCopySafe.java	Tue Jul 01 20:35:30 2014 +0000
+++ b/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",