ImageMagick-6.9.10-12差分

ImageMagick-6.9.10-11差分 - yoyaのメモの続き

The latest release of ImageMagick is version 6.9.10-12

まとめ

  • OSS Fuzz による修正。
  • SVG rotate がこっそり修正されてる。意図しない位置がズレるのを修正。
  • ScreenShot を 24bit BMPから 32bit BMP に変更。
気になる事
  • coder 周りの例外は BinaryImageException で独立したので見やすくなったかも。

差分

  • 多くの修正。初期化変数の利用、整数オーバーフロウ、メモリはみ出し。タイムアウト。 (OSS Fuzz クレジット)
coder 周りの修正
  • coders/dcm.c
    • ImageInfo の削除が間違いだった?
    • info.scale のメモリを1バイト多めに取る。(念の為? Fuzzing で何か見つかった?)
3868c3868,3872
<             ThrowDCMException(CorruptImageError,"InsufficientImageDataInFile");
---
>             {
>               read_info=DestroyImageInfo(read_info);
>               ThrowDCMException(CorruptImageError,
>                 "InsufficientImageDataInFile");
>             }
3956c3960
<         info.scale=(Quantum *) AcquireQuantumMemory(MagickMax(length,256),
---
>         info.scale=(Quantum *) AcquireQuantumMemory(MagickMax(length,MaxMap)+1,
3960c3964
<         (void) memset(info.scale,0,MagickMax(length,256)*
---
>         (void) memset(info.scale,0,(MagickMax(length,MaxMap)+1)*
  • coders/dib.c
    • ファイル終端が見つからない場合の処理。(オーバーフローする?)
593a594,595
>   if ((dib_info.image_size != 0U) && (dib_info.image_size > GetBlobSize(image)))
>     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
1018a1021
>   entry->seekable_stream=MagickTrue;
1027a1031
>   entry->seekable_stream=MagickTrue;
  • coders/dot.c
    • 作りかけ。外部コマンドで SVG に変換して内部では SVG として持つ予定。
160a161
>   (void) CopyMagickString(read_info->magick,"SVG",MaxTextExtent);
  • coders/gif.c
    • コードの整形。
423a424
>   exception=(&image->exception);
431d431
<   exception=(&image->exception);
951c951,952
<     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
---
>     ThrowBinaryImageException(CorruptImageError,"CorruptImage",
>       image->filename);
(以下、同様のコード整形)
  • coders/heic.c
    • ThrowBinaryImageException の利用。
120c120
<   ThrowBinaryException(CorruptImageError,error->message,image->filename);
---
>   ThrowBinaryImageException(CorruptImageError,error->message,image->filename);
  • coders/jpeg.c
    • ThrowBinaryImageException の利用。JPEGDescription のマクロ展開から const 変数に移行。
351c351
<         ThrowBinaryException(CorruptImageWarning,(char *) message,
---
>         ThrowBinaryImageException(CorruptImageWarning,(char *) message,
1537a1538,1541
> #define JPEGDescription "Joint Photographic Experts Group JFIF format"
> #define JPEGStringify(macro_or_string)  JPEGStringifyArg(macro_or_string)
> #define JPEGStringifyArg(contents)  #contents
>
1544,1546d1547
<   static const char
<     description[] = "Joint Photographic Experts Group JFIF format";
<
1548,1549c1549,1554
< #if defined(JPEG_LIB_VERSION)
<   (void) FormatLocaleString(version,MaxTextExtent,"%d",JPEG_LIB_VERSION);
---
> #if defined(LIBJPEG_TURBO_VERSION)
>   (void) CopyMagickString(version,"libjpeg-turbo " JPEGStringify(
>     LIBJPEG_TURBO_VERSION),MagickPathExtent);
> #elif defined(JPEG_LIB_VERSION)
>   (void) FormatLocaleString(version,MagickPathExtent,"libjpeg %d",
>     JPEG_LIB_VERSION);
1562c1567
<   entry->description=ConstantString(description);
---
>   entry->description=ConstantString(JPEGDescription);
1579c1584
<   entry->description=ConstantString(description);
---
>   entry->description=ConstantString(JPEGDescription);
1595c1600
<   entry->description=ConstantString(description);
---
>   entry->description=ConstantString(JPEGDescription);
1611c1616
<   entry->description=ConstantString(description);
---
>   entry->description=ConstantString(JPEGDescription);
1627c1632
<   entry->description=ConstantString(description);
---
>   entry->description=ConstantString(JPEGDescription);
  • coders/meta.c
    • キャストを変更。(あえて切り落とす必要なしと判断?)
932c932
<   length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
---
>   length = (((unsigned int) c1) << 8) + ((unsigned int) c2);
951c951
<   length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
---
>   length = (((unsigned int) c1) << 8) + ((unsigned int) c2);
  • coders/msl.c
    • MSLPushImage で NULL の時はファイル名出力ログを抑制。
554a555
>   if (image != (Image *) NULL)
  • coders/pcd.c
    • ThrowBinaryImageException の利用
189c189
<     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>     ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
208c208
<         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>         ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
290c290
<             ThrowBinaryException(CorruptImageError,"CorruptImage",
---
>             ThrowBinaryImageException(CorruptImageError,"CorruptImage",
  • coders/pcx.c
    • EOF チェック。画像縦横サイズとデータサイズの整合性チェック。pcx_packets に対してチェックが厳しすぎるのを修正。
340a341,342
>     if (EOFBlob(image) != MagickFalse)
>       ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
359a362,363
>     if ((MagickOffsetType) (image->columns*image->rows/255) > GetBlobSize(image))
>       ThrowPCXException(CorruptImageError,"InsufficientImageDataInFile");
408,409c412
<     if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) >
<         (pcx_packets*8U))
---
>     if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) > (pcx_packets*8U))
411c414
<     if ((MagickSizeType) (pcx_packets/10) > GetBlobSize(image))
---
>     if ((MagickSizeType) (pcx_packets/12) > GetBlobSize(image))
  • coders/png.c
    • MNG の page x, y の負値対応。
    • png:chunk-malloc-max が設定されてない時に GetMaxMemoryRequest (デフォルト値)を使う
    • パレット形式の時に透明度を一旦リセットする処理があった。
    • パレット形式出力の時、色深度を色チャネルの深度にする。
53a54
> #include "magick/colormap-private.h"
68a70
> #include "magick/memory-private.h"
1932,1933c1934,1935
<      image->page.x=(size_t)mng_get_long(&chunk->data[8]);
<      image->page.y=(size_t)mng_get_long(&chunk->data[12]);
---
>      image->page.x=(ssize_t) ((int) mng_get_long(&chunk->data[8]));
>      image->page.y=(ssize_t) ((int) mng_get_long(&chunk->data[12]));
2319a2322,2323
>     else
>       png_set_chunk_malloc_max(ping,(png_alloc_size_t) GetMaxMemoryRequest());
3255a3260,3261
>   if (status != MagickFalse)
>     status=ResetImagePixels(image,exception);
3457c3463
<         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
---
>         q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
3560c3566,3574
<           SetPixelIndex(indexes+x,*r++);
---
>         {
>           ssize_t index=ConstrainColormapIndex(image,(ssize_t) *r);
>           SetPixelRed(q,ClampToQuantum(image->colormap[index].red));
>           SetPixelGreen(q,ClampToQuantum(image->colormap[index].green));
>           SetPixelBlue(q,ClampToQuantum(image->colormap[index].blue));
>           SetPixelIndex(indexes+x,index);
>           r++;
>           q++;
>         }
3603,3613d3616
<   if (image->storage_class == PseudoClass)
<     {
<       MagickBooleanType
<         matte;
<
<       matte=image->matte;
<       image->matte=MagickFalse;
<       (void) SyncImage(image);
<       image->matte=matte;
<     }
<
8702a8706
>   image->depth=GetImageDepth(image,&image->exception);
  • coders/pnm.c
    • seekable_stream の True 代入。
441a442,443
>     if ((MagickOffsetType) (image->columns*image->rows/8) > GetBlobSize(image))
>       ThrowPNMException(CorruptImageError,"InsufficientImageDataInFile");
1427a1430
>   entry->seekable_stream=MagickTrue;
1434a1438
>   entry->seekable_stream=MagickTrue;
1441a1446
>   entry->seekable_stream=MagickTrue;
1448a1454
>   entry->seekable_stream=MagickTrue;
1456a1463
>   entry->seekable_stream=MagickTrue;
1463a1471
>   entry->seekable_stream=MagickTrue;
  • coders/psd.c
    • 変数名のリファイン、number_layers の負値対応、ThrowBinaryImageExceptionの利用。
732c732
<     value;
---
>     count;
755,756c755,756
<     p=PushLongPixel(MSBEndian,p,&value);
<     offset=(ssize_t) value;
---
>     p=PushLongPixel(MSBEndian,p,&count);
>     offset=(ssize_t) count;
1593c1593
<       number_layers=(ssize_t) ReadBlobShort(image);
---
>       number_layers=(ssize_t) ReadBlobSignedShort(image);
2519c2519
<     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>     ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
  • coders/screenshot.c
    • Windows-GDI 読み込み画像形式を 24ビット(RGB)カラーから32ビットカラー(RGBT、 T は透明度?)に変更
145c145
<     RGBTRIPLE
---
>     RGBQUAD
190c190
<       bmi.bmiHeader.biBitCount=24;
---
>       bmi.bmiHeader.biBitCount=32;
218,220c218,220
<           SetPixelRed(q,ScaleCharToQuantum(p->rgbtRed));
<           SetPixelGreen(q,ScaleCharToQuantum(p->rgbtGreen));
<           SetPixelBlue(q,ScaleCharToQuantum(p->rgbtBlue));
---
>           SetPixelRed(q,ScaleCharToQuantum(p->rgbRed));
>           SetPixelGreen(q,ScaleCharToQuantum(p->rgbGreen));
>           SetPixelBlue(q,ScaleCharToQuantum(p->rgbBlue));
  • coders/sfw.c
    • JPEG として処理する。(実際 Seattle Film Works は JPEGコンテナっぽいし、ハフマンが固定?)
353a354
>   (void) CopyMagickString(read_info->magick,"JPEG",MaxTextExtent);
  • coders/sgi.c
    • 画像縦横サイズに比してデータサイズが小さい場合にエラーにする。
377a378,379
>     if ((MagickOffsetType) (image->columns*image->rows/255) > GetBlobSize(image))
>       ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
  • coders/svg.c
    • rotate のアフィン変換の計算ミス。(回転させるとあさってな場所に移動してたかも)
2231,2232c2231,2232
<                         affine.ty=svg_info->bounds.y+x*
<                           sin(DegreesToRadians(fmod(angle,360.0)))-y*
---
>                         affine.ty=svg_info->bounds.y-x*
>                           sin(DegreesToRadians(fmod(angle,360.0)))+y*
2233a2234,2235
>                         affine.tx-=x/2.0;
>                         affine.ty-=y/2.0;
  • coders/tga.c
    • attribute に応じて Orientation を設定するのに image 構造体直に入れる事にした。(tga にセットするだけだと実際に反映されない可能性が)
145,146c145
< static Image *ReadTGAImage(const ImageInfo *image_info,
<   ExceptionInfo *exception)
---
> static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception)
277c276
<           if (image->colors > GetBlobSize(image))
---
>           if ((MagickSizeType) image->colors > GetBlobSize(image))
313c312
<         SetImageArtifact(image,"tga:image-origin","TopRight");
---
>         image->orientation=TopRightOrientation;
315c314
<         SetImageArtifact(image,"tga:image-origin","BottomRight");
---
>         image->orientation=BottomRightOrientation;
320c319
<         SetImageArtifact(image,"tga:image-origin","TopLeft");
---
>         image->orientation=TopLeftOrientation;
322c321
<         SetImageArtifact(image,"tga:image-origin","BottomLeft");
---
>         image->orientation=BottomLeftOrientation;
462c461
<                 1UL*index)];
---
>                 (ssize_t) index)];
493c492
<               index=ConstrainColormapIndex(image,((size_t) k << 8)+j);
---
>               index=ConstrainColormapIndex(image,(ssize_t) ((size_t) k << 8)+j);
839c838,844
<   value=GetImageArtifact(image,"tga:image-origin");
---
>   if ((image->orientation == BottomRightOrientation) ||
>       (image->orientation == TopRightOrientation))
>     tga_info.attributes|=(1UL << 4);
>   if ((image->orientation == TopLeftOrientation) ||
>       (image->orientation == TopRightOrientation))
>     tga_info.attributes|=(1UL << 5);
>   value=GetImageArtifact(image,"tga:image-origin");  /* deprecated */
  • coders/tiff.c
    • ThrowBinaryImageException の利用。quantum:polarity 対応
    • compress_tag の条件処理の修正。FAX3,4 と MINIS{BLACK|WHITE}の分岐判断がごっちゃ。
531c531
<     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>     ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
536c536
<     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>     ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
2532d2531
<   (void) SetImageOption(write_info,"quantum:polarity","min-is-white");
2577c2576
<       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
---
>       ThrowBinaryImageException(ResourceLimitError,"MemoryAllocationFailed",
3294a3294,3296
>         option=GetImageOption(image_info,"quantum:polarity");
>         if (option == (const char *) NULL)
>           SetQuantumMinIsWhite(quantum_info,MagickTrue);
3299a3302,3304
>         option=GetImageOption(image_info,"quantum:polarity");
>         if (option == (const char *) NULL)
>           SetQuantumMinIsWhite(quantum_info,MagickTrue);
3448,3449c3453,3454
<     if ((compress_tag == COMPRESSION_CCITTFAX3) &&
<         (photometric != PHOTOMETRIC_MINISWHITE))
---
>     if ((compress_tag == COMPRESSION_CCITTFAX3) ||
>         (compress_tag == COMPRESSION_CCITTFAX4))
3451,3456c3456,3457
<         compress_tag=COMPRESSION_NONE;
<         endian=FILLORDER_MSB2LSB;
<       }
<     else
<       if ((compress_tag == COMPRESSION_CCITTFAX4) &&
<          (photometric != PHOTOMETRIC_MINISWHITE))
---
>          if ((photometric != PHOTOMETRIC_MINISWHITE) &&
>              (photometric != PHOTOMETRIC_MINISBLACK))
3460a3462
>       }
  • coders/viff.c
    • 意味不明。作りかけ?
332a333,339
>     number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows;
>     if (number_pixels != (size_t) number_pixels)
>       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
>     if (number_pixels > GetBlobSize(image))
>       ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
>     if (number_pixels == 0)
>       ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported");
348,352d354
<     number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows;
<     if (number_pixels != (size_t) number_pixels)
<       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
<     if (number_pixels == 0)
<       ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported");
  • oders/xcf.c
    • ThrowBinaryImageException の利用。
759c759
<     ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
---
>     ThrowBinaryImageException(CorruptImageError,"InsufficientImageDataInFile",
(以下同様)
ChangeLogにない差分
  • Magick++/lib/Magick++/lib/Color.cpp
    • isValid の条件式のリファイン
<   if ((valid_ && isValid()) || (!valid_ && !isValid()))
---
>   if (bool(valid_) == bool(isValid()))
  • Magick++/lib/Magick++/lib/Image.cpp
    • matte の条件式のリファイン
<   if ((matteFlag_ && !constImage()->matte) || (constImage()->matte &&
<     !matteFlag_))
---
>   if (bool(matteFlag_) != bool(constImage()->matte))
< #      if defined(_VISUALC_)
< #        pragma message( "Magick++ lib DLL import" )
< #      endif
89,91d85
< #        if defined(__BORLANDC__)
< #          pragma message( "BCBMagick++ lib DLL export" )
< #        endif
100,102d93
< #      if defined(_VISUALC_)
< #        pragma message( "Magick++ lib DLL export" )
< #      endif
107,109d97
< #    if defined(_VISUALC_)
< #      pragma message( "Magick++ lib static interface" )
< #    endif
1171c1171
< coders_svg_la_DEPENDENCIES = $(MAGICKCORE_LIBS) $(MAGICKWAND_LIBS) \
---
> coders_svg_la_DEPENDENCIES = $(MAGICKCORE_LIBS) $(am__DEPENDENCIES_1) \
1174c1174
<       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
---
>       $(am__DEPENDENCIES_1)
  • coders/Makefile.am
    • 重複定義の整頓
< coders_svg_la_LIBADD       = $(MAGICKCORE_LIBS) $(MAGICKWAND_LIBS) $(AUTOTRACE_LIBS) $(RSVG_LIBS) $(XML_LIBS) $(LZMA_LIBS) $(ZLIB_LIBS) $(MATH_LIBS)
---
> coders_svg_la_LIBADD       = $(MAGICKCORE_LIBS) $(AUTOTRACE_LIBS) $(RSVG_LIBS) $(XML_LIBS) $(LZMA_LIBS) $(ZLIB_LIBS) $(MATH_LIBS)
  • magick/annotate.c
    • UTF 周りで色々と改造が入ってる。
行数が多すぎるので省略
  • magick/draw.c
    • ダッシュパターンのメモリサイズ拡張。その他、雑に多め(4096)にしてる所を必要な長さを計算してメモリ確保。
    • 関数の返り値で成否を見るように。
<       clone_info->dash_pattern=(double *) AcquireQuantumMemory((size_t) (x+2),
---
>       clone_info->dash_pattern=(double *) AcquireQuantumMemory((size_t) (x+4),
349c348
<         (x+2)*sizeof(*clone_info->dash_pattern));
---
>         (x+4)*sizeof(*clone_info->dash_pattern));
855a855,856
>   path_info=(PathInfo *) ResizeQuantumMemory(path_info,(size_t) (n+1),
>     sizeof(*path_info));
<略>
1427c1428
<         TraceRectangle(primitive_info,start,end);
---
>         status&=TraceRectangle(primitive_info,start,end);
1452c1453
<   TraceRectangle(primitive_info,start,end);
---
>   status&=TraceRectangle(primitive_info,start,end);
<略>
<   extent=(size_t) mvg_info->offset+pad+4096;
<   if (extent <= *mvg_info->extent)
---
>   extent=(double) mvg_info->offset+pad+PrimitiveExtentPad;
>   quantum=sizeof(**mvg_info->primitive_info);
>   if (((extent*quantum) < (double) SSIZE_MAX) &&
>       ((extent*quantum) < (double) GetMaxMemoryRequest()))
>     {
>       if (extent <= (double) *mvg_info->extent)
<略>
< static void TraceArcPath(MVGInfo *mvg_info,const PointInfo start,
---
> static MagickBooleanType TraceArcPath(MVGInfo *mvg_info,const PointInfo start,
5807a5829,5831
>   MagickBooleanType
>     status;
>
5837,5840c5861
<     {
<       TracePoint(primitive_info,end);
<       return;
<     }
---
>     return(TracePoint(primitive_info,end));
5844,5847c5865
<     {
<       TraceLine(primitive_info,start,end);
<       return;
<     }
---
>     return(TraceLine(primitive_info,start,end));
5855,5858c5873
<     {
<       TraceLine(primitive_info,start,end);
<       return;
<     }
<大量に略>
||>
- magick/enhance.c
>|c|
426a427
>   exception=(&image->exception);
635d635
<   exception=(&image->exception);
(以下同様)

- magick/fx.c

    • caption の NULL チェック
4063c4065,4077
<         *caption,
---
>         *caption;
>
>       /*
>         Generate caption image.
>       */
>       caption_image=CloneImage(image,image->columns,1,MagickTrue,exception);
>       if (caption_image == (Image *) NULL)
>         return((Image *) NULL);
>       caption=InterpretImageProperties((ImageInfo *) NULL,(Image *) image,
>         value);
>       if (caption != (char *) NULL)
>         {
>           char
4078,4083d4091
<       /*
<         Generate caption image.
<       */
<       caption_image=CloneImage(image,image->columns,1,MagickTrue,exception);
<       if (caption_image == (Image *) NULL)
<         return((Image *) NULL);
4085,4086d4092
<       caption=InterpretImageProperties((ImageInfo *) NULL,(Image *) image,
<         value);
4088,4089c4094,4095
<       count=FormatMagickCaption(caption_image,annotate_info,MagickTrue,&metrics,
<         &caption);
---
>           count=FormatMagickCaption(caption_image,annotate_info,MagickTrue,
>             &metrics,&caption);
4109a4116
>     }
  • magick/xwindow.c
    • client_name の NULL チェックをやめて、そのまま API にわたす
3322,3326d3321
<   if (client_name != (char *) NULL)
<     {
<       /*
<         Get basename of client.
<       */
  • /wand/drawing-wand.c
    • wand オブジェクトのNULLチェック
174a175
>   assert(wand != (DrawingWand *) NULL);
177d177
<   assert(wand != (DrawingWand *) NULL);
(以下同様)

ChangeLog

2018-09-16  6.9.10-12 Cristy  <quetzlzacatenango@image...>
  * Release ImageMagick version 6.9.10-12, GIT revision 13886:d2819c281:20180923

2018-09-08  6.9.10-12 Cristy  <quetzlzacatenango@image...>
  * Fixed numerous use of uninitialized values, integer overflow, memory
    exceeded, and timeouts (credit to OSS Fuzz).