src/share/classes/com/sun/crypto/provider/CipherCore.java

Print this page
8027575: b113 causing a lot of memory allocation and regression for wls_webapp_atomics

@@ -718,10 +718,19 @@
                                            + " bytes long");
         }
 
         int outLen = 0;
         if (len != 0) { // there is some work to do
+            if ((input == output)
+                 && (outputOffset <= (inputOffset + buffer.length))
+                 && (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) {
                     outLen = cipher.decrypt(buffer, 0, len, output, outputOffset);
                 } else {

@@ -730,41 +739,41 @@
                 buffered -= len;
                 if (buffered != 0) {
                     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);
+                    outputOffset += outLen;
                         buffered = 0;
                     }
-                    if (inConsumed != 0) {
-                        System.arraycopy(input, inputOffset, in, len - inConsumed, inConsumed);
-                        inputOffset += inConsumed;
-                        inputLen -= inConsumed;
-                    }
+                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
             // the total input length a multiple of blocksize when
             // padding is applied