https://issues.apache.org/bugzilla/show_bug.cgi?id=50056

           Summary: ArrayIndexOutOfBounds in AbstractWMFPainter with 1-bit
                    color images
           Product: Batik
           Version: 1.8
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Utilities
        AssignedTo: [email protected]
        ReportedBy: [email protected]


Created an attachment (id=26136)
 --> (https://issues.apache.org/bugzilla/attachment.cgi?id=26136)
The WMF file that failed

I use WMFTranscoder to convert WMF files to SVG. I found a image, that fails
with following exception:

java.lang.ArrayIndexOutOfBoundsException: 108248
    at
org.apache.batik.transcoder.wmf.tosvg.AbstractWMFPainter.getImage(AbstractWMFPainter.java:194)
    at
org.apache.batik.transcoder.wmf.tosvg.AbstractWMFPainter.getImage(AbstractWMFPainter.java:74)
    at
org.apache.batik.transcoder.wmf.tosvg.WMFPainter.paint(WMFPainter.java:859)
    at
org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder.transcode(WMFTranscoder.java:187)
    ...

The length of the array that caused the exception was 108248, so 1 byte after
the end was attempted to read.

The problem was on line 194 in AbstractWMFPainter, where next byte for the next
iteration, which could be after the end, if there is no padding.

Here is fixed code for the getImage(byte[]) method:

/** Return the image associated with a bitmap in a Metafile.
     *  24 bits and 8 bits bitmaps are handled.
     *  @param bit the bitmap byte array
     *  @return the Image associated with the bitmap (null if the dimensions
detected in the
     *     header are not consistent with the assumed dimensions)
     */
    protected BufferedImage getImage(byte[] bit) {
        // get the header of the bitmap, first the width and height
        int _width = (((int)bit[7] & 0x00ff) << 24) | (((int)bit[6] & 0x00ff)
<< 16)
                    | (((int)bit[5] & 0x00ff) << 8) | (int)bit[4] & 0x00ff;
        int _height = (((int)bit[11] & 0x00ff) << 24) | (((int)bit[10] &
0x00ff) << 16)
                    | (((int)bit[9] & 0x00ff) << 8) | (int)bit[8] & 0x00ff;

        // OK, we can safely create the data array now
        int[] bitI = new int[_width * _height];
        BufferedImage img = new BufferedImage(_width, _height,
BufferedImage.TYPE_INT_RGB);
        WritableRaster raster = img.getRaster();

        // retrieve useful informations in bitmap header
        // size of header
        int _headerSize = (((int)bit[3] & 0x00ff) << 24) | (((int)bit[2] &
0x00ff)<<16)
                            | (((int)bit[1] & 0x00ff) << 8) | (int)bit[0] &
0x00ff;
        // number of planes
        int _planes = (((int)bit[13] & 0x00ff) << 8) | (int)bit[12] & 0x00ff;
        // number of bits per pixel
        int _nbit = (((int)bit[15] & 0x00ff) << 8) | (int)bit[14] & 0x00ff;
        // compression factor : unused
        // size of the image
        int _size = (((int)bit[23] & 0x00ff) << 24) | (((int)bit[22] & 0x00ff)
<< 16)
                        | (((int)bit[21] & 0x00ff) << 8) | (int)bit[20] &
0x00ff;
        // infer the size of image if it is not given in the file
        if (_size == 0) _size = ((((_width * _nbit) + 31) & ~31 ) >> 3) *
_height;

        // number of used colors
        int _clrused = (((int)bit[35] & 0x00ff) << 24) | (((int)bit[34]&0x00ff)
<< 16)
                        | (((int)bit[33] & 0x00ff) << 8) | (int)bit[32]&0x00ff;

        // 24 bit image
        if (_nbit == 24) {
            // read the scan lines
            int pad = (_size / _height) - _width * 3;
            int offset = _headerSize; // begin to read data after header
            // populate the int array
            for (int j = 0; j < _height; j++) {
                for (int i = 0; i < _width; i++) {
                    bitI[_width * (_height - j - 1) + i] =
                        (255 & 0x00ff) << 24 | (((int)bit[offset+2] & 0x00ff)
<< 16)
                        | (((int)bit[offset+1] & 0x00ff) << 8) |
(int)bit[offset] & 0x00ff;
                    offset += 3;
                }
                offset += pad;
            }
        // 8 bit image
        } else if (_nbit == 8) {
            // Determine the number of colors
            int nbColors = 0;
            if (_clrused > 0) nbColors = _clrused;
            else nbColors = (1 & 0x00ff) << 8;
            // Read the palette colors.
            int offset = _headerSize;
            int[]  palette = new int[nbColors];
            for (int i = 0; i < nbColors; i++) {
                palette[i] = (255 & 0x00ff) << 24 | (((int)bit[offset+2] &
0x00ff) << 16)
                            | (((int)bit[offset+1] & 0x00ff) << 8)
                            | (int)bit[offset] & 0x00ff;
                offset += 4;
            }

            // populate the int array
            /* need to recalculate size because the offset used for palette
must be substracted
             * to overall size, else we will go after the end of the byte
array...
             */
            _size = bit.length - offset;
            int pad = (_size / _height) - _width;
            for (int j = 0; j < _height; j++) {
                for (int i = 0; i < _width; i++) {
                    bitI[_width*(_height-j-1)+i] = palette [((int)bit[offset] &
0x00ff)];
                    offset++;
                }
                offset += pad;
            }
        // black and white image
        } else if (_nbit == 1) {
            // 2 colors only (black and white image)
            int nbColors = 2;
            // Read the palette colors.
            int offset = _headerSize;
            int[]  palette = new int[nbColors];
            for (int i = 0; i < nbColors; i++) {
                palette[i] = (255 & 0x00ff) << 24 | (((int)bit[offset+2] &
0x00ff) << 16)
                            | (((int)bit[offset+1] & 0x00ff) << 8)
                            | (int)bit[offset] & 0x00ff;
                offset += 4;
            }

            // populate the int array : each pixel corresponds to a bit in the
byte array
            int pos = 7;
            byte currentByte = bit[offset];
            // padded to long words
            int pad = (_size / _height) - _width/8;
            for (int j = 0; j < _height; j++) {
                for (int i = 0; i < _width; i++) {
                    if ((currentByte & (1 << pos)) != 0)
bitI[_width*(_height-j-1)+i] = palette[1];
                    else bitI[_width*(_height-j-1)+i] = palette[0];
                    pos--;
                    if (pos == -1) {
                        pos = 7;
                        offset++;
                        if (offset < bit.length)
                            currentByte = bit[offset];
                    }
                }
                offset +=pad;
                pos = 7;
                if (offset < bit.length) currentByte = bit[offset];
            }
        }
        raster.setDataElements(0, 0, _width, _height, bitI);
        return img;
    }

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to