Hello Jay This is a minor change on top of webrev.02. Looks good.
Thanks Have a good day Prahalad N. -----Original Message----- From: Sergey Bylokhov Sent: Tuesday, January 16, 2018 10:42 PM To: Jayathirth D V; 2d-dev Subject: Re: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper Looks fine. Thank you for clarification. On 14/01/2018 23:08, Jayathirth D V wrote: > Hello Sergey, > > Thanks for reviewing the changes. > > The maximum value of inputBands & bitDepth can be 4 & 16. Also in > readHeader() we verify the values present in inputBands & bitDepth and if > they are not in required bounds we throw IIOException. So (inputBands * > bitDepth) will not cause overflow. > > Also I noticed that we need to use Math.multiplyExact() in skipPass() > function too where we have same calculation. > So I have updated the code to reflect the same. > > Please review the updated webrev: > http://cr.openjdk.java.net/~jdv/8191174/webrev.03/ > > Thanks, > Jay > > -----Original Message----- > From: Sergey Bylokhov > Sent: Saturday, January 13, 2018 9:00 AM > To: Jayathirth D V; 2d-dev > Subject: Re: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws > IllegalArgumentException because ScanlineStride calculation logic is > not proper > > Hi, Jay. > Can you please confirm that it is not possible to get overflow in: > "inputBands * bitDepth"? > 1051 int bitsPerRow = Math.multiplyExact((inputBands * bitDepth), > passWidth); > > On 08/01/2018 02:04, Jayathirth D V wrote: >> As you have mentioned throwing "Pixel stride times width must be less than >> or equal to the scanline stride" is not proper in this scenario as image >> contains proper width as per PNG specification. >> Thanks for pointing to Math.multiplyExact() function and it is very >> beneficial for solving this issue. While calculating bytesPerRow itself we >> can use Math.multiplyExact() and throw "int overflow" ArithmeticException >> and it will be wrapped into IIOException because of changes present in >> https://bugs.openjdk.java.net/browse/JDK-8190332 . >> >> By doing this we will not have multiple "Caused by" chain and we will be >> throwing proper exception as per ImageIO specification. >> Please find updated webrev for review: >> http://cr.openjdk.java.net/~jdv/8191174/webrev.02/ >> >> Thanks, >> Jay >> >> -----Original Message----- >> From: Sergey Bylokhov >> Sent: Saturday, January 06, 2018 2:45 PM >> To: Prahalad Kumar Narayanan; Jayathirth D V; 2d-dev >> Subject: Re: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws >> IllegalArgumentException because ScanlineStride calculation logic is >> not proper >> >> Probably we can use Math.multiplyExact()? The current exception text wrapped >> a few times "Pixel stride times width must be less than or equal to the >> scanline stride" is not strictly correct because it is possible that the >> image itself has correct data, but we cannot handle it because of overflow. >> >> On 28/12/2017 22:49, Prahalad Kumar Narayanan wrote: >>> Hello Jay >>> >>> Good day to you. >>> >>> The code changes wrap the IllegalArgumentException in IIOException. >>> This approach is better & aligns with how OutOfMemoryError was wrapped to >>> fix JDK-8190332. >>> >>> The only point that I 'm not sure is- whether we could wrap >>> IllegalArgumentException twice before throwing to the user code. >>> >>> javax.imageio.IIOException: Error reading PNG image data >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read >>> at java.desktop/javax.imageio.ImageIO.read >>> ... >>> Caused by: javax.imageio.IIOException: Caught exception during read: >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage >>> ... >>> Caused by: java.lang.IllegalArgumentException: Pixel stride times width >>> must be less than or equal to the scanline stride >>> at >>> java.desktop/java.awt.image.PixelInterleavedSampleModel.<init> >>> at >>> java.desktop/java.awt.image.Raster.createInterleavedRaster >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.createRaster >>> >>> Since there are multiple levels of same exception, programmer could have >>> trouble getting the cause using getCause() method. >>> However, Invoking printStackTrace() on the outer most exception object >>> gives complete call stack (as listed above). >>> So I think, this should be ok. >>> >>> I would like to know of others' opinion too. >>> >>> Thank you >>> Have a good day >>> >>> Prahalad N. >>> >>> >>> -----Original Message----- >>> From: Jayathirth D V >>> Sent: Thursday, December 28, 2017 3:43 PM >>> To: Prahalad Kumar Narayanan; 2d-dev >>> Subject: RE: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws >>> IllegalArgumentException because ScanlineStride calculation logic is >>> not proper >>> >>> Hi Prahalad, >>> >>> Thanks for your valuable inputs. >>> >>> Even though the fix resolves the issue for the particular test case we have >>> it will not solve the buffer overflow problem as you have mentioned in >>> highest limit case or many other cases where the computed value is very >>> high. >>> >>> Also we cannot change datatype of bytesPerRow/eltsPerRow as they are used >>> in many passed to many other Raster and Stream API's. The best approach to >>> resolve this issue would be to wrap the Exception that we are getting while >>> creating Raster/SampleModel into an IIOException as we have done in >>> https://bugs.openjdk.java.net/browse/JDK-8190332 . By doing this we will >>> abide by specification and also we will have complete stack of why we got >>> the exception so that it can be debugged properly in future. >>> >>> Please find updated webrev for review: >>> http://cr.openjdk.java.net/~jdv/8191174/webrev.01/ >>> >>> Thanks, >>> Jay >>> >>> -----Original Message----- >>> From: Prahalad Kumar Narayanan >>> Sent: Tuesday, December 19, 2017 3:08 PM >>> To: Jayathirth D V; 2d-dev >>> Subject: RE: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws >>> IllegalArgumentException because ScanlineStride calculation logic is >>> not proper >>> >>> >>> Hello Jay >>> >>> Good day to you. >>> >>> I don't think it's possible to fix this issue despite having intermediate " >>> long " variable to hold intermediate bits per pixel. >>> Here is a simple math that considers the worst case scenario with max >>> values: >>> >>> . As per the PNG specification, the maximum permissible width, number of >>> bands, bit-depth are as follows- >>> max_width : (2 ^ 31) - 1 = 2147483647 >>> max_input_bands = 4 >>> max_bit_depth = 16 (2 Bytes) >>> >>> . As per the logic proposed in the fix, the intermediate bits per row would >>> fit into a "long" variable but bytes per pixel would not fit into "int" >>> variable. >>> // Fits into "long" data type >>> max_bits_per_row = max_width * max_input_bands * max_bit_depth >>> = 2147483647 x 4 x 16 >>> = 137438953408 >>> >>> // Does not fit into "int" data type >>> max_bytes_per_row = max_bits_per_row + 7 / 8 >>> = 17179869176 >>> = (0x 3FFFFFFF8 >>> - Goes beyond 4B boundary) >>> >>> // Upon division by 2 for 16-bit images >>> max_elts_per_row = max_bytes_per_row / 2 >>> = 8589934588 >>> = (0x 1FFFFFFFC - >>> Goes beyond 4B boundary) >>> >>> . If we intend to store bytes per row (and eltsPerRow which is scanline >>> stride) in a "long" variable, the same cannot be sent to Raster APIs >>> because the APIs accept "int" type for scanline stride in arguments list. >>> Going by the Raster APIs used in PNGImageReader, a proper fix would >>> require changes to its APIs as well to handle such large scanline stride >>> values. >>> >>> Thank you >>> Have a good day >>> >>> Prahalad N. >>> >>> ----- Original Message ----- >>> From: Jayathirth D V >>> Sent: Thursday, December 14, 2017 1:48 PM >>> To: 2d-dev >>> Subject: [OpenJDK 2D-Dev] RFR JDK-8191174: PngReader throws >>> IllegalArgumentException because ScanlineStride calculation logic is >>> not proper >>> >>> Hello All, >>> >>> Please review the following fix in JDK : >>> >>> Bug : https://bugs.openjdk.java.net/browse/JDK-8191174 >>> Webrev : http://cr.openjdk.java.net/~jdv/8191174/webrev.00/ >>> >>> Issue : When we try to read PNG image with large width we throw >>> undocumented IllegalArgumentException with message "Pixel stride times >>> width must be less than or equal to the scanline stride". >>> >>> Exception in thread "main" java.lang.IllegalArgumentException: Pixel >>> stride times width must be less than or equal to the scanline stride >>> at >>> java.desktop/java.awt.image.PixelInterleavedSampleModel.<init>(Pixel >>> I >>> n >>> terleavedSampleModel.java:101) >>> at >>> java.desktop/java.awt.image.Raster.createInterleavedRaster(Raster.ja >>> v >>> a >>> :642) >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.createRaster >>> ( >>> P >>> NGImageReader.java:974) >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(P >>> N >>> G >>> ImageReader.java:1099) >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage( >>> P >>> N >>> GImageReader.java:1295) >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(PN >>> G >>> I >>> mageReader.java:1420) >>> at >>> java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(PNGImag >>> e >>> R >>> eader.java:1699) >>> at >>> java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468) >>> at >>> java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1363) >>> at >>> PngReaderLargeWidthStrideTest.main(PngReaderLargeWidthStrideTest.java: >>> 50) >>> >>> Root cause : We use large width present in IHDR and calculate elements per >>> row which is passed as scanlinestride for creating the required raster and >>> its corresponding sample model. When the call reaches creation of >>> PixelInterleavedSampleModel it checks the condition of (pixelStride * w) > >>> scanlineStride. Since in our case we pass this condition it throws >>> IllegalArgumentException. We have invalid scanlineStride value because when >>> we calculate elements per row/bytes per row value in PNGImageReader the >>> integer variable buffer is overflowed and we maintain invalid value for >>> bytesPerRow. >>> >>> Solution : We can maintain the intermediate bitsPerRow value in long >>> datatype and calculate bytesPerRow using the long value and then typecast >>> it to int bytesPerRow variable. By doing this we will maintain the required >>> scanlineStride/eltsPerRow value properly. After this solution we will throw >>> proper IIOException because of changes present in JDK-8190332 and not the >>> undocumented IllegalArgumentException. >>> >>> Thanks, >>> Jay >>> >> >> >> -- >> Best regards, Sergey. >> > > > -- > Best regards, Sergey. > -- Best regards, Sergey.