Index: GraphicsMagick-1.3.29/coders/xwd.c =================================================================== --- GraphicsMagick-1.3.29.orig/coders/xwd.c 2017-12-09 21:02:45.000000000 +0100 +++ GraphicsMagick-1.3.29/coders/xwd.c 2019-04-30 12:01:19.204675966 +0200 @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2015 GraphicsMagick Group +% Copyright (C) 2003-2019 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -96,6 +96,143 @@ static unsigned int IsXWD(const unsigned #if defined(HasX11) #include "magick/xwindow.h" + +static void TraceXWDHeader(const XWDFileHeader *header) +{ + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "XWDFileHeader:\n" + " header_size : %u\n" + " file_version : %u\n" + " pixmap_format : %s\n" + " pixmap_depth : %u\n" + " pixmap_width : %u\n" + " pixmap_height : %u\n" + " xoffset : %u\n" + " byte_order : %s\n" + " bitmap_unit : %u\n" + " bitmap_bit_order : %s\n" + " bitmap_pad : %u\n" + " bits_per_pixel : %u\n" + " bytes_per_line : %u\n" + " visual_class : %s\n" + " red_mask : 0x%06X\n" + " green_mask : 0x%06X\n" + " blue_mask : 0x%06X\n" + " bits_per_rgb : %u\n" + " colormap_entries : %u\n" + " ncolors : %u\n" + " window_width : %u\n" + " window_height : %u\n" + " window_x : %u\n" + " window_y : %u\n" + " window_bdrwidth : %u", + (unsigned int) header->header_size, + (unsigned int) header->file_version, + /* (unsigned int) header->pixmap_format, */ + (header->pixmap_format == XYBitmap ? "XYBitmap" : + (header->pixmap_format == XYPixmap ? "XYPixmap" : + (header->pixmap_format == ZPixmap ? "ZPixmap" : "?"))), + (unsigned int) header->pixmap_depth, + (unsigned int) header->pixmap_width, + (unsigned int) header->pixmap_height, + (unsigned int) header->xoffset, + (header->byte_order == MSBFirst? "MSBFirst" : + (header->byte_order == LSBFirst ? "LSBFirst" : "?")), + (unsigned int) header->bitmap_unit, + (header->bitmap_bit_order == MSBFirst? "MSBFirst" : + (header->bitmap_bit_order == LSBFirst ? "LSBFirst" : + "?")), + (unsigned int) header->bitmap_pad, + (unsigned int) header->bits_per_pixel, + (unsigned int) header->bytes_per_line, + (header->visual_class == StaticGray ? "StaticGray" : + (header->visual_class == GrayScale ? "GrayScale" : + (header->visual_class == StaticColor ? "StaticColor" : + (header->visual_class == PseudoColor ? "PseudoColor" : + (header->visual_class == TrueColor ? "TrueColor" : + (header->visual_class == DirectColor ? + "DirectColor" : "?")))))), + (unsigned int) header->red_mask, + (unsigned int) header->green_mask, + (unsigned int) header->blue_mask, + (unsigned int) header->bits_per_rgb, + (unsigned int) header->colormap_entries, + (unsigned int) header->ncolors, + (unsigned int) header->window_width, + (unsigned int) header->window_height, + (unsigned int) header->window_x, + (unsigned int) header->window_y, + (unsigned int) header->window_bdrwidth + ); +} + +static void TraceXImage(const XImage *ximage) +{ + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "XImage:\n" + " width: %d\n" + " height: %d\n" + " xoffset: %d\n" + " format: %s\n" + " data: %p\n" + " byte_order: %s\n" + " bitmap_unit: %d\n" + " bitmap_bit_order: %s\n" + " bitmap_pad: %d\n" + " depth: %d\n" + " bytes_per_line: %d\n" + " bits_per_pixel: %d\n" + " red_mask: %06lX\n" + " green_mask: %06lX\n" + " blue_mask: %06lX\n", + ximage->width, + ximage->height, + ximage->xoffset, + (ximage->format == XYBitmap ? "XYBitmap" : + (ximage->format == XYPixmap ? "XYPixmap" : + (ximage->format == ZPixmap ? "ZPixmap" : "?"))), + ximage->data, + (ximage->byte_order == MSBFirst? "MSBFirst" : + (ximage->byte_order == LSBFirst ? "LSBFirst" : "?")), + ximage->bitmap_unit, + (ximage->bitmap_bit_order == MSBFirst? "MSBFirst" : + (ximage->bitmap_bit_order == LSBFirst ? "LSBFirst" : + "?")), + ximage->bitmap_pad, + ximage->depth, + ximage->bytes_per_line, + ximage->bits_per_pixel, + ximage->red_mask, + ximage->green_mask, + ximage->blue_mask); +} + +/* + Compute required allocation sizes + + FIXME: This is still a work in progress. + + BitmapUnit (pixmap_depth) is the size of each data unit in each + scan line. This value may be 8, 16, or 32. + + BitmapPad (bitmap_pad) is the number of bits of padding added to + each scan line. This value may be 8, 16, or 32. +*/ +static MagickPassFail BytesPerLine(size_t *bytes_per_line, + size_t *scanline_bits, + const size_t pixmap_width, + const size_t pixmap_depth, + const size_t bitmap_pad) +{ + *bytes_per_line=0; + *scanline_bits=MagickArraySize(pixmap_width,pixmap_depth); + if ((*scanline_bits > 0) && (((~(size_t)0) - *scanline_bits > (bitmap_pad)-1))) + *bytes_per_line=((((*scanline_bits)+((bitmap_pad)-1))/ + (bitmap_pad))*((bitmap_pad) >> 3)); + + return (*bytes_per_line !=0 && *scanline_bits != 0) ? MagickPass : MagickFail; +} + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -129,7 +266,6 @@ static unsigned int IsXWD(const unsigned */ #define ThrowXWDReaderException(code_,reason_,image_) \ do { \ - MagickFreeMemory(comment); \ if (ximage) \ MagickFreeMemory(ximage->data); \ MagickFreeMemory(ximage); \ @@ -140,7 +276,7 @@ do { \ static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception) { char - *comment = (char *) NULL; + comment[MaxTextExtent]; Image *image; @@ -211,71 +347,11 @@ static Image *ReadXWDImage(const ImageIn if (*(char *) &lsb_first) MSBOrderLong((unsigned char *) &header,sz_XWDheader); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "XWDFileHeader:\n" - " header_size : %u\n" - " file_version : %u\n" - " pixmap_format : %s\n" - " pixmap_depth : %u\n" - " pixmap_width : %u\n" - " pixmap_height : %u\n" - " xoffset : %u\n" - " byte_order : %s\n" - " bitmap_unit : %u\n" - " bitmap_bit_order : %s\n" - " bitmap_pad : %u\n" - " bits_per_pixel : %u\n" - " bytes_per_line : %u\n" - " visual_class : %s\n" - " red_mask : 0x%06X\n" - " green_mask : 0x%06X\n" - " blue_mask : 0x%06X\n" - " bits_per_rgb : %u\n" - " colormap_entries : %u\n" - " ncolors : %u\n" - " window_width : %u\n" - " window_height : %u\n" - " window_x : %u\n" - " window_y : %u\n" - " window_bdrwidth : %u", - (unsigned int) header.header_size, - (unsigned int) header.file_version, - /* (unsigned int) header.pixmap_format, */ - (header.pixmap_format == XYBitmap ? "XYBitmap" : - (header.pixmap_format == XYPixmap ? "XYPixmap" : - (header.pixmap_format == ZPixmap ? "ZPixmap" : "?"))), - (unsigned int) header.pixmap_depth, - (unsigned int) header.pixmap_width, - (unsigned int) header.pixmap_height, - (unsigned int) header.xoffset, - (header.byte_order == MSBFirst? "MSBFirst" : - (header.byte_order == LSBFirst ? "LSBFirst" : "?")), - (unsigned int) header.bitmap_unit, - (header.bitmap_bit_order == MSBFirst? "MSBFirst" : - (header.bitmap_bit_order == LSBFirst ? "LSBFirst" : - "?")), - (unsigned int) header.bitmap_pad, - (unsigned int) header.bits_per_pixel, - (unsigned int) header.bytes_per_line, - (header.visual_class == StaticGray ? "StaticGray" : - (header.visual_class == GrayScale ? "GrayScale" : - (header.visual_class == StaticColor ? "StaticColor" : - (header.visual_class == PseudoColor ? "PseudoColor" : - (header.visual_class == TrueColor ? "TrueColor" : - (header.visual_class == DirectColor ? - "DirectColor" : "?")))))), - (unsigned int) header.red_mask, - (unsigned int) header.green_mask, - (unsigned int) header.blue_mask, - (unsigned int) header.bits_per_rgb, - (unsigned int) header.colormap_entries, - (unsigned int) header.ncolors, - (unsigned int) header.window_width, - (unsigned int) header.window_height, - (unsigned int) header.window_x, - (unsigned int) header.window_y, - (unsigned int) header.window_bdrwidth - ); + /* + Trace XWD header + */ + if (image->logging) + TraceXWDHeader(&header); /* Check to see if the dump file is in the proper format. @@ -283,7 +359,19 @@ static Image *ReadXWDImage(const ImageIn if (header.file_version != XWD_FILE_VERSION) ThrowXWDReaderException(CorruptImageError,InvalidFileFormatVersion,image); if (header.header_size < sz_XWDheader) - ThrowXWDReaderException(CorruptImageError,CorruptImage,image); + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + + /* + Detect signed integer overflow + */ + if (((magick_uint32_t) header.pixmap_depth | header.pixmap_format | + header.xoffset | header.pixmap_width | header.pixmap_height | + header.bitmap_pad | header.bytes_per_line | header.byte_order | + header.bitmap_unit | header.bitmap_bit_order | + header.bits_per_pixel) >> 31) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + + /* Display classes used in opening the connection */ switch (header.visual_class) { case StaticGray: @@ -295,37 +383,152 @@ static Image *ReadXWDImage(const ImageIn break; default: { - ThrowXWDReaderException(CorruptImageError,CorruptImage,image); + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); } } + + /* XYBitmap, XYPixmap, ZPixmap */ switch (header.pixmap_format) { - case XYBitmap: - case XYPixmap: - case ZPixmap: + case XYBitmap: /* 1 bit bitmap format */ + if (header.pixmap_depth != 1) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + break; + case XYPixmap: /* Single plane bitmap. */ + case ZPixmap: /* Bitmap with 2 or more planes */ + if ((header.pixmap_depth < 1) || (header.pixmap_depth > 32)) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); break; default: { - ThrowXWDReaderException(CorruptImageError,CorruptImage,image); + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); } } + /* Data byte order, LSBFirst, MSBFirst */ + switch (header.byte_order) + { + case LSBFirst: + case MSBFirst: + break; + default: + { + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + } + } + + /* Quant. of scanline 8, 16, 32 */ + switch (header.bitmap_unit) + { + case 8: + case 16: + case 32: + break; + default: + { + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + } + } + + /* LSBFirst, MSBFirst */ + switch (header.bitmap_bit_order) + { + case LSBFirst: + case MSBFirst: + break; + default: + { + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + } + } + + /* 8, 16, 32 either XY or ZPixmap */ + if ((header.pixmap_format == XYPixmap) || (header.pixmap_format == ZPixmap)) + switch (header.bitmap_pad) + { + case 8: + case 16: + case 32: + break; + default: + { + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + } + } + + /* xoffset should be in the bounds of pixmap_width */ + if (header.xoffset >= header.pixmap_width) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + + /* Bits per pixel (ZPixmap) */ + switch (header.visual_class) + { + case StaticGray: + case GrayScale: + /* Gray-scale image */ + if (header.bits_per_pixel != 1) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + break; + case StaticColor: + case PseudoColor: + /* Color-mapped image */ + if ((header.bits_per_pixel < 1) || (header.bits_per_pixel > 15) || + (header.ncolors == 0)) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + break; + case TrueColor: + case DirectColor: + /* True-color image */ + if ((header.bits_per_pixel != 16) && (header.bits_per_pixel != 24) && + (header.bits_per_pixel != 32)) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + break; + } + + /* Place an arbitrary limit on colormap size */ + if (header.ncolors > 4096) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + + + /* 8, 16, 32 either XY or ZPixmap */ + if ((header.bitmap_pad % 8 != 0) || (header.bitmap_pad > 32)) + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + + { + size_t + bytes_per_line=0, + scanline_bits; + + if (BytesPerLine(&bytes_per_line,&scanline_bits, + header.pixmap_width,header.pixmap_depth,header.bitmap_pad) + == MagickFail) + ThrowReaderException(CoderError,ArithmeticOverflow,image); + + if (header.bytes_per_line < bytes_per_line) + { + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "Header bytes_per_line = %" MAGICK_SIZE_T_F "u," + " expected %" MAGICK_SIZE_T_F "u", + (MAGICK_SIZE_T) header.bytes_per_line, + (MAGICK_SIZE_T) bytes_per_line); + ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + } + } + + /* Retrieve comment (if any) */ length=header.header_size-sz_XWDheader; - if (length > ((~0UL)/sizeof(*comment))) + if (length >= MaxTextExtent) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); - comment=MagickAllocateMemory(char *,length+1); - if (comment == (char *) NULL) - ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed,image); count=ReadBlob(image,length,comment); if (count != length) ThrowXWDReaderException(CorruptImageError,UnableToReadWindowNameFromDumpFile, image); comment[length]='\0'; (void) SetImageAttribute(image,"comment",comment); - MagickFreeMemory(comment); + /* Initialize the X image. @@ -348,37 +551,29 @@ static Image *ReadXWDImage(const ImageIn ximage->red_mask=header.red_mask; ximage->green_mask=header.green_mask; ximage->blue_mask=header.blue_mask; - /* - XImage uses signed integers rather than unsigned. Check for - overflow due to assignment. - */ - if (ximage->width < 0 || - ximage->height < 0 || - ximage->format < 0 || - ximage->byte_order < 0 || - ximage->bitmap_unit < 0 || - ximage->bitmap_bit_order < 0 || - ximage->bitmap_pad < 0 || - ximage->depth < 0 || - ximage->bytes_per_line < 0 || - ximage->bits_per_pixel < 0) - ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); - /* Guard against buffer overflow in libX11. */ - if (ximage->bits_per_pixel > 32 || ximage->bitmap_unit > 32) - ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); + status=XInitImage(ximage); if (status == False) ThrowXWDReaderException(CorruptImageError,UnrecognizedXWDHeader,image); - image->columns=ximage->width; - image->rows=ximage->height; + + if (image->logging) + TraceXImage(ximage); + + image->columns=(unsigned long) ximage->width; + image->rows=(unsigned long) ximage->height; if (!image_info->ping) if (CheckImagePixelLimits(image, exception) != MagickPass) ThrowXWDReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); image->depth=8; - if ((header.ncolors == 0U) || - ((ximage->red_mask != 0) || - (ximage->green_mask != 0) || - (ximage->blue_mask != 0))) + + /* + FIXME: This block of logic should be re-worked. + */ + if ((header.visual_class != StaticGray) && + ((header.ncolors == 0U) || + ((ximage->red_mask != 0) || + (ximage->green_mask != 0) || + (ximage->blue_mask != 0)))) { image->storage_class=DirectClass; if (!image_info->ping) @@ -390,8 +585,8 @@ static Image *ReadXWDImage(const ImageIn else { image->storage_class=PseudoClass; + image->colors=header.visual_class == StaticGray ? 2 : header.ncolors; /* FIXME! */ } - image->colors=header.ncolors; if (!image_info->ping) { /* @@ -403,17 +598,14 @@ static Image *ReadXWDImage(const ImageIn XWDColor color; - register long + register unsigned int i; - length=(size_t) header.ncolors; - if (length > ((~0UL)/sizeof(*colors))) - ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); - colors=MagickAllocateArray(XColor *,length,sizeof(XColor)); + colors=MagickAllocateArray(XColor *,header.ncolors,sizeof(XColor)); if (colors == (XColor *) NULL) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed, image); - for (i=0; i < (long) header.ncolors; i++) + for (i=0; i < header.ncolors; i++) { count=ReadBlob(image,sz_XWDColor,(char *) &color); if (count != sz_XWDColor) @@ -430,7 +622,7 @@ static Image *ReadXWDImage(const ImageIn */ lsb_first=1; if (*(char *) &lsb_first) - for (i=0; i < (long) header.ncolors; i++) + for (i=0; i < header.ncolors; i++) { MSBOrderLong((unsigned char *) &colors[i].pixel, sizeof(unsigned long)); @@ -444,18 +636,32 @@ static Image *ReadXWDImage(const ImageIn /* Allocate the pixel buffer. */ -#define XWD_OVERFLOW(c,a,b) ((b) != 0 && ((c)/((size_t) b) != ((size_t) a))) - length=ximage->bytes_per_line*ximage->height; - if (XWD_OVERFLOW(length,ximage->bytes_per_line,ximage->height)) + length=MagickArraySize(ximage->bytes_per_line,ximage->height); + if (0 == length) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed,image); if (ximage->format != ZPixmap) { - size_t tmp=length; - length*=ximage->depth; - if (XWD_OVERFLOW(length,tmp,ximage->depth)) + length=MagickArraySize(length,ximage->depth); + if (0 == length) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed, image); } + { + + magick_off_t + file_size; + + file_size=GetBlobSize(image); + + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + "File size %" MAGICK_OFF_F "d," + "Pixels allocation size %" MAGICK_SIZE_T_F "u", + file_size, (MAGICK_SIZE_T) length); + + if ((file_size != 0) && ((size_t) file_size < length)) + ThrowXWDReaderException(CorruptImageError,UnexpectedEndOfFile,image); + } + ximage->data=MagickAllocateMemory(char *,length); if (ximage->data == (char *) NULL) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed,image); @@ -507,7 +713,7 @@ static Image *ReadXWDImage(const ImageIn /* Convert X image to DirectClass packets. */ - if (image->colors != 0) + if (header.ncolors != 0) { for (y=0; y < (long) image->rows; y++) { @@ -519,12 +725,15 @@ static Image *ReadXWDImage(const ImageIn pixel=XGetPixel(ximage,(int) x,(int) y); index_val=(unsigned short) ((pixel >> red_shift) & red_mask); + VerifyColormapIndexWithColors(image,index_val,header.ncolors); q->red=ScaleShortToQuantum(colors[index_val].red); index_val=(unsigned short) ((pixel >> green_shift) & green_mask); + VerifyColormapIndexWithColors(image,index_val,header.ncolors); q->green=ScaleShortToQuantum(colors[index_val].green); index_val=(unsigned short) ((pixel >> blue_shift) & blue_mask); + VerifyColormapIndexWithColors(image,index_val,header.ncolors); q->blue=ScaleShortToQuantum(colors[index_val].blue); q++; } @@ -575,17 +784,21 @@ static Image *ReadXWDImage(const ImageIn /* Convert X image to PseudoClass packets. */ - register long + register unsigned int i; if (!AllocateImageColormap(image,image->colors)) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed, image); - for (i=0; i < (long) image->colors; i++) + if (colors != (XColor *) NULL) { - image->colormap[i].red=ScaleShortToQuantum(colors[i].red); - image->colormap[i].green=ScaleShortToQuantum(colors[i].green); - image->colormap[i].blue=ScaleShortToQuantum(colors[i].blue); + const unsigned int min_colors = Min(image->colors,header.ncolors); + for (i=0; i < min_colors; i++) + { + image->colormap[i].red=ScaleShortToQuantum(colors[i].red); + image->colormap[i].green=ScaleShortToQuantum(colors[i].green); + image->colormap[i].blue=ScaleShortToQuantum(colors[i].blue); + } } for (y=0; y < (long) image->rows; y++) { @@ -722,16 +935,16 @@ ModuleExport void UnregisterXWDImage(voi */ static unsigned int WriteXWDImage(const ImageInfo *image_info,Image *image) { - long + unsigned long y; register const PixelPacket *p; - register long + register unsigned long x; - register long + register unsigned int i; register unsigned char @@ -740,17 +953,22 @@ static unsigned int WriteXWDImage(const unsigned char *pixels; + unsigned int + bits_per_pixel; + size_t - pixels_size; + bytes_per_line=0, + scanline_bits, + scanline_pad=0; unsigned int + bitmap_pad; + + MagickPassFail status; unsigned long - bits_per_pixel, - bytes_per_line, - lsb_first, - scanline_pad; + lsb_first; XWDFileHeader xwd_info; @@ -763,7 +981,7 @@ static unsigned int WriteXWDImage(const assert(image != (Image *) NULL); assert(image->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); - if (status == False) + if (status == MagickFail) ThrowWriterException(FileOpenError,UnableToOpenFile,image); (void) TransformColorspace(image,RGBColorspace); /* @@ -771,6 +989,40 @@ static unsigned int WriteXWDImage(const */ if ((image->storage_class == PseudoClass) && (image->colors > 256)) SetImageType(image,TrueColorType); + + /* + Compute required allocation sizes + + BitmapUnit is the size of each data unit in each scan line. This + value may be 8, 16, or 32. + + BitmapPad is the number of bits of padding added to each scan + line. This value may be 8, 16, or 32. + */ + bits_per_pixel=(image->storage_class == DirectClass ? 24 : 8); + bitmap_pad=(image->storage_class == DirectClass ? 32 : 8); + + if (BytesPerLine(&bytes_per_line,&scanline_bits,image->columns, + bits_per_pixel,bitmap_pad) != MagickFail) + scanline_pad=(bytes_per_line-(scanline_bits >> 3)); + + if (image->logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " image->columns=%lu," + " bits_per_pixel=%u," + " bytes_per_line=%" MAGICK_SIZE_T_F "u," + " bitmap_pad=%u", + image->columns, + bits_per_pixel, + (MAGICK_SIZE_T) bytes_per_line, + bitmap_pad); + if ((scanline_bits == 0) || (bytes_per_line < (scanline_bits >> 3))) + ThrowWriterException(CoderError,ArithmeticOverflow,image); + + if (((bytes_per_line & 0x7fffffff) != bytes_per_line) || + ((image->rows & 0x7fffffff) != image->rows)) + ThrowWriterException(CoderError,ImageColumnOrRowSizeIsNotSupported,image); + /* Initialize XWD file header. */ @@ -785,19 +1037,14 @@ static unsigned int WriteXWDImage(const xwd_info.byte_order=(CARD32) MSBFirst; xwd_info.bitmap_unit=(CARD32) (image->storage_class == DirectClass ? 32 : 8); xwd_info.bitmap_bit_order=(CARD32) MSBFirst; - xwd_info.bitmap_pad=(CARD32) (image->storage_class == DirectClass ? 32 : 8); - bits_per_pixel=(image->storage_class == DirectClass ? 24 : 8); + xwd_info.bitmap_pad=(CARD32) bitmap_pad; xwd_info.bits_per_pixel=(CARD32) bits_per_pixel; - bytes_per_line=(CARD32) ((((xwd_info.bits_per_pixel* - xwd_info.pixmap_width)+((xwd_info.bitmap_pad)-1))/ - (xwd_info.bitmap_pad))*((xwd_info.bitmap_pad) >> 3)); xwd_info.bytes_per_line=(CARD32) bytes_per_line; xwd_info.visual_class=(CARD32) (image->storage_class == DirectClass ? DirectColor : PseudoColor); xwd_info.red_mask=(CARD32) (image->storage_class == DirectClass ? 0xff0000 : 0); - xwd_info.green_mask=(CARD32) - (image->storage_class == DirectClass ? 0xff00 : 0); + xwd_info.green_mask=(CARD32)(image->storage_class == DirectClass ? 0xff00 : 0); xwd_info.blue_mask=(CARD32) (image->storage_class == DirectClass ? 0xff : 0); xwd_info.bits_per_rgb=(CARD32) (image->storage_class == DirectClass ? 24 : 8); xwd_info.colormap_entries=(CARD32) @@ -809,6 +1056,20 @@ static unsigned int WriteXWDImage(const xwd_info.window_x=0; xwd_info.window_y=0; xwd_info.window_bdrwidth=(CARD32) 0; + + /* + Trace XWD header + */ + if (image->logging) + TraceXWDHeader(&xwd_info); + + /* + Allocate memory for pixels. + */ + pixels=MagickAllocateMemory(unsigned char *,bytes_per_line); + if (pixels == (unsigned char *) NULL) + ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); + /* Write XWD header. */ @@ -832,7 +1093,7 @@ static unsigned int WriteXWDImage(const colors=MagickAllocateArray(XColor *,image->colors,sizeof(XColor)); if (colors == (XColor *) NULL) ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); - for (i=0; i < (long) image->colors; i++) + for (i=0; i < image->colors; i++) { colors[i].pixel=i; colors[i].red=ScaleQuantumToShort(image->colormap[i].red); @@ -846,30 +1107,22 @@ static unsigned int WriteXWDImage(const MSBOrderShort((unsigned char *) &colors[i].red,3*sizeof(short)); } } - for (i=0; i < (long) image->colors; i++) + for (i=0; i < image->colors; i++) { color.pixel=(CARD32) colors[i].pixel; color.red=colors[i].red; color.green=colors[i].green; color.blue=colors[i].blue; color.flags=colors[i].flags; - (void) WriteBlob(image,sz_XWDColor,(char *) &color); + if (WriteBlob(image,sz_XWDColor,(char *) &color) != sz_XWDColor) + break; } MagickFreeMemory(colors); } /* - Allocate memory for pixels. - */ - scanline_pad=(bytes_per_line-((image->columns*bits_per_pixel) >> 3)); - pixels_size=image->columns*(image->storage_class == PseudoClass ? 1 : 3)+scanline_pad; - pixels=MagickAllocateMemory(unsigned char *,pixels_size); - if (pixels == (unsigned char *) NULL) - ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); - (void) memset(pixels,0,pixels_size); - /* Convert MIFF to XWD raster pixels. */ - for (y=0; y < (long) image->rows; y++) + for (y=0; y < image->rows; y++) { p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) @@ -882,12 +1135,12 @@ static unsigned int WriteXWDImage(const *indexes; indexes=AccessImmutableIndexes(image); - for (x=0; x < (long) image->columns; x++) + for (x=0; x < image->columns; x++) *q++=(unsigned char) indexes[x]; } else { - for (x=(long) image->columns; x > 0; x--) + for (x=0; x < image->columns; x++) { *q++=ScaleQuantumToChar(p->red); @@ -898,7 +1151,8 @@ static unsigned int WriteXWDImage(const } for (x=(long) scanline_pad; x > 0; x--) *q++=0; - (void) WriteBlob(image,(size_t) (q-pixels),(char *) pixels); + if (WriteBlob(image,(size_t) (q-pixels),(char *) pixels) != (size_t) (q-pixels)) + break; if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, @@ -908,6 +1162,6 @@ static unsigned int WriteXWDImage(const } MagickFreeMemory(pixels); CloseBlob(image); - return(True); + return (y < image->rows ? MagickFail : MagickPass); } #endif