diff -r f23912ce3308 -r 31e01190e3c5 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Fri Jan 27 15:37:47 2017 +0530 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Mon Jan 30 16:32:46 2017 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -1559,6 +1559,59 @@ decodeRLE4(imSize, padding, values, bdata); } + private boolean copyRLE4ScanlineToDst(int lineNo, + byte[] val, + byte[] bdata) throws IOException { + // Return value + boolean isSuccess = false; + + // Reusing the code to copy 1 row of pixels or scanline to required + // destination buffer. + if (lineNo >= sourceRegion.y && + lineNo < sourceRegion.y + sourceRegion.height) { + if (noTransform) { + int pos = lineNo * (width + 1 >> 1); + for(int i = 0, j = 0; i < width >> 1; i++) + bdata[pos++] = + (byte)((val[j++] << 4) | val[j++]); + if ((width & 1) == 1) + bdata[pos] |= val[width - 1] << 4; + + processImageUpdate(bi, 0, lineNo, + destinationRegion.width, 1, 1, 1, + new int[]{0}); + isSuccess = true; + } else if ((lineNo - sourceRegion.y) % scaleY == 0) { + int lineStride = + ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride(); + int currentLine = (lineNo - sourceRegion.y) / scaleY + + destinationRegion.y; + int pos = currentLine * lineStride; + pos += destinationRegion.x >> 1; + int shift = (1 - (destinationRegion.x & 1)) << 2; + for (int i = sourceRegion.x; + i < sourceRegion.x + sourceRegion.width; + i += scaleX) { + bdata[pos] |= val[i] << shift; + shift += 4; + if (shift == 4) { + pos++; + } + shift &= 7; + } + processImageUpdate(bi, 0, currentLine, + destinationRegion.width, 1, 1, 1, + new int[]{0}); + isSuccess = true; + } + // Ensure to reset the scanline buffer once the copy is complete. + for(int scIndex = 0; scIndex < width; scIndex++) { + val[scIndex] = 0; + } + } + return isSuccess; + } + private void decodeRLE4(int imSize, int padding, byte[] values, @@ -1568,57 +1621,22 @@ int value; boolean flag = false; int lineNo = isBottomUp ? height - 1 : 0; - int lineStride = - ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride(); int finished = 0; - while (count != imSize) { + // Ensure the image has sufficient data before proceeding to decode + while ((count + 1) < imSize) { value = values[count++] & 0xFF; if (value == 0) { - // Absolute mode switch(values[count++] & 0xFF) { case 0: // End-of-scanline marker - // End-of-scanline marker - if (lineNo >= sourceRegion.y && - lineNo < sourceRegion.y + sourceRegion.height) { - if (noTransform) { - int pos = lineNo * (width + 1 >> 1); - for(int i = 0, j = 0; i < width >> 1; i++) - bdata[pos++] = - (byte)((val[j++] << 4) | val[j++]); - if ((width & 1) == 1) - bdata[pos] |= val[width - 1] << 4; - - processImageUpdate(bi, 0, lineNo, - destinationRegion.width, 1, 1, 1, - new int[]{0}); - finished++; - } else if ((lineNo - sourceRegion.y) % scaleY == 0) { - int currentLine = (lineNo - sourceRegion.y) / scaleY + - destinationRegion.y; - int pos = currentLine * lineStride; - pos += destinationRegion.x >> 1; - int shift = (1 - (destinationRegion.x & 1)) << 2; - for (int i = sourceRegion.x; - i < sourceRegion.x + sourceRegion.width; - i += scaleX) { - bdata[pos] |= val[i] << shift; - shift += 4; - if (shift == 4) { - pos++; - } - shift &= 7; - } - processImageUpdate(bi, 0, currentLine, - destinationRegion.width, 1, 1, 1, - new int[]{0}); - finished++; - } + // Copy the decoded scanline to destination + if (copyRLE4ScanlineToDst(lineNo, val, bdata)) { + finished++; } processImageProgress(100.0F * finished / destinationRegion.height); lineNo += isBottomUp ? -1 : 1; @@ -1633,21 +1651,61 @@ case 1: // End-of-RLE marker flag = true; + + // Check if the last decoded scanline was copied to + // destination bitmap + if (l != 0) { + // Copy the decoded scanline to destination + if (copyRLE4ScanlineToDst(lineNo, val, bdata)) { + finished++; + } + processImageProgress(100.0F * finished / destinationRegion.height); + lineNo += isBottomUp ? -1 : 1; + l = 0; + } break; case 2: // delta or vector marker - int xoff = values[count++] & 0xFF; - int yoff = values[count] & 0xFF; - // Move to the position xoff, yoff down - l += xoff + yoff*width; + if ((count + 1) < imSize) { + int xoff = values[count++] & 0xFF; + int yoff = values[count++] & 0xFF; + + // Check if the yOffset shifts the decoding to another + // row. In such cases, the decoded pixels in scanline + // buffer-val must be copied to the destination image. + if (yoff != 0) { + // Copy the decoded scanline to destination + if (copyRLE4ScanlineToDst(lineNo, val, bdata)) { + finished++; + } + processImageProgress(100.0F * finished + / destinationRegion.height); + lineNo += isBottomUp ? -yoff : yoff; + } + + // Move to the position (xoff, yoff). Since l-is used + // to index into the scanline buffer, the accumulated + // offset is limited to the width of the scanline + l += xoff + yoff*width; + l %= width; + } break; default: int end = values[count-1] & 0xFF; - for (int i=0; i> 4 - : (values[count++] & 0x0f)); + byte readByte = 0; + // Ensure to check if the source index-count, does not + // exceed the source image size + for (int i = 0; (i < end) && (count < imSize); i++) { + readByte = (byte)(((i & 1) == 0) ? + (values[count] & 0xf0) >> 4 : + (values[count++] & 0x0f)); + // Ensure to check if scanline index-l, does not + // exceed the scanline buffer size (width of image) + if (l < width) { + val[l++] = readByte; + } } // When end is odd, the above for loop does not @@ -1665,10 +1723,14 @@ } } else { // Encoded mode - int alternate[] = { (values[count] & 0xf0) >> 4, - values[count] & 0x0f }; - for (int i=0; (i < value) && (l < width); i++) { - val[l++] = (byte)alternate[i & 1]; + // Ensure to check if the source index-count, does not + // exceed the source image size + if (count < imSize) { + int alternate[] = { (values[count] & 0xf0) >> 4, + values[count] & 0x0f }; + for (int i=0; (i < value) && (l < width); i++) { + val[l++] = (byte)alternate[i & 1]; + } } count++;