Merge lp:~noskcaj/ubuntu/saucy/imagemagick/lp1218248 into lp:ubuntu/saucy/imagemagick

Proposed by Jackson Doak
Status: Rejected
Rejected by: Iain Lane
Proposed branch: lp:~noskcaj/ubuntu/saucy/imagemagick/lp1218248
Merge into: lp:ubuntu/saucy/imagemagick
Diff against target: 2014 lines (+1959/-1)
6 files modified
.pc/0008-memory-corruption-while-processing-GIF-comments.patch/coders/gif.c (+1917/-0)
.pc/applied-patches (+1/-0)
coders/gif.c (+4/-1)
debian/changelog (+7/-0)
debian/patches/0008-memory-corruption-while-processing-GIF-comments.patch (+29/-0)
debian/patches/series (+1/-0)
To merge this branch: bzr merge lp:~noskcaj/ubuntu/saucy/imagemagick/lp1218248
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+183315@code.launchpad.net

Description of the change

To post a comment you must log in.
Revision history for this message
Robie Basak (racb) wrote :

Thanks for preparing this merge. It looks like this issue was prioritised for security and fixed by Marc's security upload in 8:6.7.7.10-5ubuntu3 before a sponsor could review it.

Unmerged revisions

41. By Jackson Doak

Add 0008-memory-corruption-while-processing-GIF-comments.patch from debian experiemental and imagemagick upstream

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/0008-memory-corruption-while-processing-GIF-comments.patch'
2=== added file '.pc/0008-memory-corruption-while-processing-GIF-comments.patch/.timestamp'
3=== added directory '.pc/0008-memory-corruption-while-processing-GIF-comments.patch/coders'
4=== added file '.pc/0008-memory-corruption-while-processing-GIF-comments.patch/coders/gif.c'
5--- .pc/0008-memory-corruption-while-processing-GIF-comments.patch/coders/gif.c 1970-01-01 00:00:00 +0000
6+++ .pc/0008-memory-corruption-while-processing-GIF-comments.patch/coders/gif.c 2013-08-31 08:11:44 +0000
7@@ -0,0 +1,1917 @@
8+/*
9+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10+% %
11+% %
12+% %
13+% GGGG IIIII FFFFF %
14+% G I F %
15+% G GG I FFF %
16+% G G I F %
17+% GGG IIIII F %
18+% %
19+% %
20+% Read/Write Compuserv Graphics Interchange Format %
21+% %
22+% Software Design %
23+% John Cristy %
24+% July 1992 %
25+% %
26+% %
27+% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
28+% dedicated to making software imaging solutions freely available. %
29+% %
30+% You may not use this file except in compliance with the License. You may %
31+% obtain a copy of the License at %
32+% %
33+% http://www.imagemagick.org/script/license.php %
34+% %
35+% Unless required by applicable law or agreed to in writing, software %
36+% distributed under the License is distributed on an "AS IS" BASIS, %
37+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
38+% See the License for the specific language governing permissions and %
39+% limitations under the License. %
40+% %
41+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42+%
43+%
44+*/
45+
46
47+/*
48+ Include declarations.
49+*/
50+#include "magick/studio.h"
51+#include "magick/attribute.h"
52+#include "magick/blob.h"
53+#include "magick/blob-private.h"
54+#include "magick/cache.h"
55+#include "magick/color.h"
56+#include "magick/color-private.h"
57+#include "magick/colormap.h"
58+#include "magick/colormap-private.h"
59+#include "magick/colorspace.h"
60+#include "magick/colorspace-private.h"
61+#include "magick/exception.h"
62+#include "magick/exception-private.h"
63+#include "magick/image.h"
64+#include "magick/image-private.h"
65+#include "magick/list.h"
66+#include "magick/profile.h"
67+#include "magick/magick.h"
68+#include "magick/memory_.h"
69+#include "magick/monitor.h"
70+#include "magick/monitor-private.h"
71+#include "magick/option.h"
72+#include "magick/pixel-private.h"
73+#include "magick/property.h"
74+#include "magick/quantize.h"
75+#include "magick/quantum-private.h"
76+#include "magick/static.h"
77+#include "magick/string_.h"
78+#include "magick/string-private.h"
79+#include "magick/module.h"
80+
81
82+/*
83+ Define declarations.
84+*/
85+#define MaximumLZWBits 12
86+#define MaximumLZWCode (1UL << MaximumLZWBits)
87+
88
89+/*
90+ Typdef declarations.
91+*/
92+typedef struct _LZWCodeInfo
93+{
94+ unsigned char
95+ buffer[280];
96+
97+ size_t
98+ count,
99+ bit;
100+
101+ MagickBooleanType
102+ eof;
103+} LZWCodeInfo;
104+
105+typedef struct _LZWStack
106+{
107+ size_t
108+ *codes,
109+ *index,
110+ *top;
111+} LZWStack;
112+
113+typedef struct _LZWInfo
114+{
115+ Image
116+ *image;
117+
118+ LZWStack
119+ *stack;
120+
121+ MagickBooleanType
122+ genesis;
123+
124+ size_t
125+ data_size,
126+ maximum_data_value,
127+ clear_code,
128+ end_code,
129+ bits,
130+ first_code,
131+ last_code,
132+ maximum_code,
133+ slot,
134+ *table[2];
135+
136+ LZWCodeInfo
137+ code_info;
138+} LZWInfo;
139+
140
141+/*
142+ Forward declarations.
143+*/
144+static inline int
145+ GetNextLZWCode(LZWInfo *,const size_t);
146+
147+static MagickBooleanType
148+ WriteGIFImage(const ImageInfo *,Image *);
149+
150+static ssize_t
151+ ReadBlobBlock(Image *,unsigned char *);
152+
153
154+/*
155+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156+% %
157+% %
158+% %
159+% D e c o d e I m a g e %
160+% %
161+% %
162+% %
163+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164+%
165+% DecodeImage uncompresses an image via GIF-coding.
166+%
167+% The format of the DecodeImage method is:
168+%
169+% MagickBooleanType DecodeImage(Image *image,const ssize_t opacity)
170+%
171+% A description of each parameter follows:
172+%
173+% o image: the address of a structure of type Image.
174+%
175+% o opacity: The colormap index associated with the transparent color.
176+%
177+*/
178+
179+static LZWInfo *RelinquishLZWInfo(LZWInfo *lzw_info)
180+{
181+ if (lzw_info->table[0] != (size_t *) NULL)
182+ lzw_info->table[0]=(size_t *) RelinquishMagickMemory(
183+ lzw_info->table[0]);
184+ if (lzw_info->table[1] != (size_t *) NULL)
185+ lzw_info->table[1]=(size_t *) RelinquishMagickMemory(
186+ lzw_info->table[1]);
187+ if (lzw_info->stack != (LZWStack *) NULL)
188+ {
189+ if (lzw_info->stack->codes != (size_t *) NULL)
190+ lzw_info->stack->codes=(size_t *) RelinquishMagickMemory(
191+ lzw_info->stack->codes);
192+ lzw_info->stack=(LZWStack *) RelinquishMagickMemory(lzw_info->stack);
193+ }
194+ lzw_info=(LZWInfo *) RelinquishMagickMemory(lzw_info);
195+ return((LZWInfo *) NULL);
196+}
197+
198+static inline void ResetLZWInfo(LZWInfo *lzw_info)
199+{
200+ size_t
201+ one;
202+
203+ lzw_info->bits=lzw_info->data_size+1;
204+ one=1;
205+ lzw_info->maximum_code=one << lzw_info->bits;
206+ lzw_info->slot=lzw_info->maximum_data_value+3;
207+ lzw_info->genesis=MagickTrue;
208+}
209+
210+static LZWInfo *AcquireLZWInfo(Image *image,const size_t data_size)
211+{
212+ LZWInfo
213+ *lzw_info;
214+
215+ register ssize_t
216+ i;
217+
218+ size_t
219+ one;
220+
221+ lzw_info=(LZWInfo *) AcquireMagickMemory(sizeof(*lzw_info));
222+ if (lzw_info == (LZWInfo *) NULL)
223+ return((LZWInfo *) NULL);
224+ (void) ResetMagickMemory(lzw_info,0,sizeof(*lzw_info));
225+ lzw_info->image=image;
226+ lzw_info->data_size=data_size;
227+ one=1;
228+ lzw_info->maximum_data_value=(one << data_size)-1;
229+ lzw_info->clear_code=lzw_info->maximum_data_value+1;
230+ lzw_info->end_code=lzw_info->maximum_data_value+2;
231+ lzw_info->table[0]=(size_t *) AcquireQuantumMemory(MaximumLZWCode,
232+ sizeof(*lzw_info->table));
233+ lzw_info->table[1]=(size_t *) AcquireQuantumMemory(MaximumLZWCode,
234+ sizeof(*lzw_info->table));
235+ if ((lzw_info->table[0] == (size_t *) NULL) ||
236+ (lzw_info->table[1] == (size_t *) NULL))
237+ {
238+ lzw_info=RelinquishLZWInfo(lzw_info);
239+ return((LZWInfo *) NULL);
240+ }
241+ for (i=0; i <= (ssize_t) lzw_info->maximum_data_value; i++)
242+ {
243+ lzw_info->table[0][i]=0;
244+ lzw_info->table[1][i]=(size_t) i;
245+ }
246+ ResetLZWInfo(lzw_info);
247+ lzw_info->code_info.buffer[0]='\0';
248+ lzw_info->code_info.buffer[1]='\0';
249+ lzw_info->code_info.count=2;
250+ lzw_info->code_info.bit=8*lzw_info->code_info.count;
251+ lzw_info->code_info.eof=MagickFalse;
252+ lzw_info->genesis=MagickTrue;
253+ lzw_info->stack=(LZWStack *) AcquireMagickMemory(sizeof(*lzw_info->stack));
254+ if (lzw_info->stack == (LZWStack *) NULL)
255+ {
256+ lzw_info=RelinquishLZWInfo(lzw_info);
257+ return((LZWInfo *) NULL);
258+ }
259+ lzw_info->stack->codes=(size_t *) AcquireQuantumMemory(2UL*
260+ MaximumLZWCode,sizeof(*lzw_info->stack->codes));
261+ if (lzw_info->stack->codes == (size_t *) NULL)
262+ {
263+ lzw_info=RelinquishLZWInfo(lzw_info);
264+ return((LZWInfo *) NULL);
265+ }
266+ lzw_info->stack->index=lzw_info->stack->codes;
267+ lzw_info->stack->top=lzw_info->stack->codes+2*MaximumLZWCode;
268+ return(lzw_info);
269+}
270+
271+static inline int GetNextLZWCode(LZWInfo *lzw_info,const size_t bits)
272+{
273+ int
274+ code;
275+
276+ register ssize_t
277+ i;
278+
279+ size_t
280+ one;
281+
282+ while (((lzw_info->code_info.bit+bits) > (8*lzw_info->code_info.count)) &&
283+ (lzw_info->code_info.eof == MagickFalse))
284+ {
285+ ssize_t
286+ count;
287+
288+ lzw_info->code_info.buffer[0]=lzw_info->code_info.buffer[
289+ lzw_info->code_info.count-2];
290+ lzw_info->code_info.buffer[1]=lzw_info->code_info.buffer[
291+ lzw_info->code_info.count-1];
292+ lzw_info->code_info.bit-=8*(lzw_info->code_info.count-2);
293+ lzw_info->code_info.count=2;
294+ count=ReadBlobBlock(lzw_info->image,&lzw_info->code_info.buffer[
295+ lzw_info->code_info.count]);
296+ if (count > 0)
297+ lzw_info->code_info.count+=count;
298+ else
299+ lzw_info->code_info.eof=MagickTrue;
300+ }
301+ if ((lzw_info->code_info.bit+bits) > (8*lzw_info->code_info.count))
302+ return(-1);
303+ code=0;
304+ one=1;
305+ for (i=0; i < (ssize_t) bits; i++)
306+ {
307+ code|=((lzw_info->code_info.buffer[lzw_info->code_info.bit/8] &
308+ (one << (lzw_info->code_info.bit % 8))) != 0) << i;
309+ lzw_info->code_info.bit++;
310+ }
311+ return(code);
312+}
313+
314+static inline int PopLZWStack(LZWStack *stack_info)
315+{
316+ if (stack_info->index <= stack_info->codes)
317+ return(-1);
318+ stack_info->index--;
319+ return((int) *stack_info->index);
320+}
321+
322+static inline void PushLZWStack(LZWStack *stack_info,const size_t value)
323+{
324+ if (stack_info->index >= stack_info->top)
325+ return;
326+ *stack_info->index=value;
327+ stack_info->index++;
328+}
329+
330+static int ReadBlobLZWByte(LZWInfo *lzw_info)
331+{
332+ int
333+ code;
334+
335+ ssize_t
336+ count;
337+
338+ size_t
339+ one,
340+ value;
341+
342+ if (lzw_info->stack->index != lzw_info->stack->codes)
343+ return(PopLZWStack(lzw_info->stack));
344+ if (lzw_info->genesis != MagickFalse)
345+ {
346+ lzw_info->genesis=MagickFalse;
347+ do
348+ {
349+ lzw_info->first_code=(size_t) GetNextLZWCode(lzw_info,
350+ lzw_info->bits);
351+ lzw_info->last_code=lzw_info->first_code;
352+ } while (lzw_info->first_code == lzw_info->clear_code);
353+ return((int) lzw_info->first_code);
354+ }
355+ code=GetNextLZWCode(lzw_info,lzw_info->bits);
356+ if (code < 0)
357+ return(code);
358+ if ((size_t) code == lzw_info->clear_code)
359+ {
360+ ResetLZWInfo(lzw_info);
361+ return(ReadBlobLZWByte(lzw_info));
362+ }
363+ if ((size_t) code == lzw_info->end_code)
364+ return(-1);
365+ if ((size_t) code < lzw_info->slot)
366+ value=(size_t) code;
367+ else
368+ {
369+ PushLZWStack(lzw_info->stack,lzw_info->first_code);
370+ value=lzw_info->last_code;
371+ }
372+ count=0;
373+ while (value > lzw_info->maximum_data_value)
374+ {
375+ if ((size_t) count > MaximumLZWCode)
376+ return(-1);
377+ count++;
378+ if ((size_t) value > MaximumLZWCode)
379+ return(-1);
380+ PushLZWStack(lzw_info->stack,lzw_info->table[1][value]);
381+ value=lzw_info->table[0][value];
382+ }
383+ lzw_info->first_code=lzw_info->table[1][value];
384+ PushLZWStack(lzw_info->stack,lzw_info->first_code);
385+ one=1;
386+ if (lzw_info->slot < MaximumLZWCode)
387+ {
388+ lzw_info->table[0][lzw_info->slot]=lzw_info->last_code;
389+ lzw_info->table[1][lzw_info->slot]=lzw_info->first_code;
390+ lzw_info->slot++;
391+ if ((lzw_info->slot >= lzw_info->maximum_code) &&
392+ (lzw_info->bits < MaximumLZWBits))
393+ {
394+ lzw_info->bits++;
395+ lzw_info->maximum_code=one << lzw_info->bits;
396+ }
397+ }
398+ lzw_info->last_code=(size_t) code;
399+ return(PopLZWStack(lzw_info->stack));
400+}
401+
402+static MagickBooleanType DecodeImage(Image *image,const ssize_t opacity)
403+{
404+ ExceptionInfo
405+ *exception;
406+
407+ IndexPacket
408+ index;
409+
410+ int
411+ c;
412+
413+ ssize_t
414+ offset,
415+ y;
416+
417+ LZWInfo
418+ *lzw_info;
419+
420+ unsigned char
421+ data_size;
422+
423+ size_t
424+ pass;
425+
426+ /*
427+ Allocate decoder tables.
428+ */
429+ assert(image != (Image *) NULL);
430+ assert(image->signature == MagickSignature);
431+ if (image->debug != MagickFalse)
432+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
433+ data_size=(unsigned char) ReadBlobByte(image);
434+ if (data_size > MaximumLZWBits)
435+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
436+ lzw_info=AcquireLZWInfo(image,data_size);
437+ if (lzw_info == (LZWInfo *) NULL)
438+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
439+ image->filename);
440+ exception=(&image->exception);
441+ pass=0;
442+ offset=0;
443+ for (y=0; y < (ssize_t) image->rows; y++)
444+ {
445+ register IndexPacket
446+ *restrict indexes;
447+
448+ register ssize_t
449+ x;
450+
451+ register PixelPacket
452+ *restrict q;
453+
454+ q=GetAuthenticPixels(image,0,offset,image->columns,1,exception);
455+ if (q == (PixelPacket *) NULL)
456+ break;
457+ indexes=GetAuthenticIndexQueue(image);
458+ for (x=0; x < (ssize_t) image->columns; )
459+ {
460+ c=ReadBlobLZWByte(lzw_info);
461+ if (c < 0)
462+ break;
463+ index=ConstrainColormapIndex(image,(size_t) c);
464+ SetPixelIndex(indexes+x,index);
465+ SetPixelRGBO(q,image->colormap+(ssize_t) index);
466+ SetPixelOpacity(q,(ssize_t) index == opacity ?
467+ TransparentOpacity : OpaqueOpacity);
468+ x++;
469+ q++;
470+ }
471+ if (x < (ssize_t) image->columns)
472+ break;
473+ if (image->interlace == NoInterlace)
474+ offset++;
475+ else
476+ switch (pass)
477+ {
478+ case 0:
479+ default:
480+ {
481+ offset+=8;
482+ if (offset >= (ssize_t) image->rows)
483+ {
484+ pass++;
485+ offset=4;
486+ }
487+ break;
488+ }
489+ case 1:
490+ {
491+ offset+=8;
492+ if (offset >= (ssize_t) image->rows)
493+ {
494+ pass++;
495+ offset=2;
496+ }
497+ break;
498+ }
499+ case 2:
500+ {
501+ offset+=4;
502+ if (offset >= (ssize_t) image->rows)
503+ {
504+ pass++;
505+ offset=1;
506+ }
507+ break;
508+ }
509+ case 3:
510+ {
511+ offset+=2;
512+ break;
513+ }
514+ }
515+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
516+ break;
517+ }
518+ lzw_info=RelinquishLZWInfo(lzw_info);
519+ if (y < (ssize_t) image->rows)
520+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
521+ return(MagickTrue);
522+}
523+
524
525+/*
526+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527+% %
528+% %
529+% %
530+% E n c o d e I m a g e %
531+% %
532+% %
533+% %
534+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535+%
536+% EncodeImage compresses an image via GIF-coding.
537+%
538+% The format of the EncodeImage method is:
539+%
540+% MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
541+% const size_t data_size)
542+%
543+% A description of each parameter follows:
544+%
545+% o image_info: the image info.
546+%
547+% o image: the address of a structure of type Image.
548+%
549+% o data_size: The number of bits in the compressed packet.
550+%
551+*/
552+static MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
553+ const size_t data_size)
554+{
555+#define MaxCode(number_bits) ((one << (number_bits))-1)
556+#define MaxHashTable 5003
557+#define MaxGIFBits 12UL
558+#define MaxGIFTable (1UL << MaxGIFBits)
559+#define GIFOutputCode(code) \
560+{ \
561+ /* \
562+ Emit a code. \
563+ */ \
564+ if (bits > 0) \
565+ datum|=(code) << bits; \
566+ else \
567+ datum=code; \
568+ bits+=number_bits; \
569+ while (bits >= 8) \
570+ { \
571+ /* \
572+ Add a character to current packet. \
573+ */ \
574+ packet[length++]=(unsigned char) (datum & 0xff); \
575+ if (length >= 254) \
576+ { \
577+ (void) WriteBlobByte(image,(unsigned char) length); \
578+ (void) WriteBlob(image,length,packet); \
579+ length=0; \
580+ } \
581+ datum>>=8; \
582+ bits-=8; \
583+ } \
584+ if (free_code > max_code) \
585+ { \
586+ number_bits++; \
587+ if (number_bits == MaxGIFBits) \
588+ max_code=MaxGIFTable; \
589+ else \
590+ max_code=MaxCode(number_bits); \
591+ } \
592+}
593+
594+ IndexPacket
595+ index;
596+
597+ register ssize_t
598+ i;
599+
600+ short
601+ *hash_code,
602+ *hash_prefix,
603+ waiting_code;
604+
605+ size_t
606+ bits,
607+ clear_code,
608+ datum,
609+ end_of_information_code,
610+ free_code,
611+ length,
612+ max_code,
613+ next_pixel,
614+ number_bits,
615+ one,
616+ pass;
617+
618+ ssize_t
619+ displacement,
620+ offset,
621+ k,
622+ y;
623+
624+ unsigned char
625+ *packet,
626+ *hash_suffix;
627+
628+ /*
629+ Allocate encoder tables.
630+ */
631+ assert(image != (Image *) NULL);
632+ one=1;
633+ packet=(unsigned char *) AcquireQuantumMemory(256,sizeof(*packet));
634+ hash_code=(short *) AcquireQuantumMemory(MaxHashTable,sizeof(*hash_code));
635+ hash_prefix=(short *) AcquireQuantumMemory(MaxHashTable,sizeof(*hash_prefix));
636+ hash_suffix=(unsigned char *) AcquireQuantumMemory(MaxHashTable,
637+ sizeof(*hash_suffix));
638+ if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) ||
639+ (hash_prefix == (short *) NULL) ||
640+ (hash_suffix == (unsigned char *) NULL))
641+ {
642+ if (packet != (unsigned char *) NULL)
643+ packet=(unsigned char *) RelinquishMagickMemory(packet);
644+ if (hash_code != (short *) NULL)
645+ hash_code=(short *) RelinquishMagickMemory(hash_code);
646+ if (hash_prefix != (short *) NULL)
647+ hash_prefix=(short *) RelinquishMagickMemory(hash_prefix);
648+ if (hash_suffix != (unsigned char *) NULL)
649+ hash_suffix=(unsigned char *) RelinquishMagickMemory(hash_suffix);
650+ return(MagickFalse);
651+ }
652+ /*
653+ Initialize GIF encoder.
654+ */
655+ number_bits=data_size;
656+ max_code=MaxCode(number_bits);
657+ clear_code=((short) one << (data_size-1));
658+ end_of_information_code=clear_code+1;
659+ free_code=clear_code+2;
660+ length=0;
661+ datum=0;
662+ bits=0;
663+ for (i=0; i < MaxHashTable; i++)
664+ hash_code[i]=0;
665+ GIFOutputCode(clear_code);
666+ /*
667+ Encode pixels.
668+ */
669+ offset=0;
670+ pass=0;
671+ waiting_code=0;
672+ for (y=0; y < (ssize_t) image->rows; y++)
673+ {
674+ register const IndexPacket
675+ *restrict indexes;
676+
677+ register const PixelPacket
678+ *restrict p;
679+
680+ register ssize_t
681+ x;
682+
683+ p=GetVirtualPixels(image,0,offset,image->columns,1,&image->exception);
684+ if (p == (const PixelPacket *) NULL)
685+ break;
686+ indexes=GetVirtualIndexQueue(image);
687+ if (y == 0)
688+ waiting_code=(short) (*indexes);
689+ for (x=(ssize_t) (y == 0 ? 1 : 0); x < (ssize_t) image->columns; x++)
690+ {
691+ /*
692+ Probe hash table.
693+ */
694+ index=(IndexPacket) ((size_t) GetPixelIndex(indexes+x) & 0xff);
695+ p++;
696+ k=(ssize_t) (((size_t) index << (MaxGIFBits-8))+waiting_code);
697+ if (k >= MaxHashTable)
698+ k-=MaxHashTable;
699+ next_pixel=MagickFalse;
700+ displacement=1;
701+ if (hash_code[k] > 0)
702+ {
703+ if ((hash_prefix[k] == waiting_code) &&
704+ (hash_suffix[k] == (unsigned char) index))
705+ {
706+ waiting_code=hash_code[k];
707+ continue;
708+ }
709+ if (k != 0)
710+ displacement=MaxHashTable-k;
711+ for ( ; ; )
712+ {
713+ k-=displacement;
714+ if (k < 0)
715+ k+=MaxHashTable;
716+ if (hash_code[k] == 0)
717+ break;
718+ if ((hash_prefix[k] == waiting_code) &&
719+ (hash_suffix[k] == (unsigned char) index))
720+ {
721+ waiting_code=hash_code[k];
722+ next_pixel=MagickTrue;
723+ break;
724+ }
725+ }
726+ if (next_pixel == MagickTrue)
727+ continue;
728+ }
729+ GIFOutputCode((size_t) waiting_code);
730+ if (free_code < MaxGIFTable)
731+ {
732+ hash_code[k]=(short) free_code++;
733+ hash_prefix[k]=waiting_code;
734+ hash_suffix[k]=(unsigned char) index;
735+ }
736+ else
737+ {
738+ /*
739+ Fill the hash table with empty entries.
740+ */
741+ for (k=0; k < MaxHashTable; k++)
742+ hash_code[k]=0;
743+ /*
744+ Reset compressor and issue a clear code.
745+ */
746+ free_code=clear_code+2;
747+ GIFOutputCode(clear_code);
748+ number_bits=data_size;
749+ max_code=MaxCode(number_bits);
750+ }
751+ waiting_code=(short) index;
752+ }
753+ if (image_info->interlace == NoInterlace)
754+ offset++;
755+ else
756+ switch (pass)
757+ {
758+ case 0:
759+ default:
760+ {
761+ offset+=8;
762+ if (offset >= (ssize_t) image->rows)
763+ {
764+ pass++;
765+ offset=4;
766+ }
767+ break;
768+ }
769+ case 1:
770+ {
771+ offset+=8;
772+ if (offset >= (ssize_t) image->rows)
773+ {
774+ pass++;
775+ offset=2;
776+ }
777+ break;
778+ }
779+ case 2:
780+ {
781+ offset+=4;
782+ if (offset >= (ssize_t) image->rows)
783+ {
784+ pass++;
785+ offset=1;
786+ }
787+ break;
788+ }
789+ case 3:
790+ {
791+ offset+=2;
792+ break;
793+ }
794+ }
795+ }
796+ /*
797+ Flush out the buffered code.
798+ */
799+ GIFOutputCode((size_t) waiting_code);
800+ GIFOutputCode(end_of_information_code);
801+ if (bits > 0)
802+ {
803+ /*
804+ Add a character to current packet.
805+ */
806+ packet[length++]=(unsigned char) (datum & 0xff);
807+ if (length >= 254)
808+ {
809+ (void) WriteBlobByte(image,(unsigned char) length);
810+ (void) WriteBlob(image,length,packet);
811+ length=0;
812+ }
813+ }
814+ /*
815+ Flush accumulated data.
816+ */
817+ if (length > 0)
818+ {
819+ (void) WriteBlobByte(image,(unsigned char) length);
820+ (void) WriteBlob(image,length,packet);
821+ }
822+ /*
823+ Free encoder memory.
824+ */
825+ hash_suffix=(unsigned char *) RelinquishMagickMemory(hash_suffix);
826+ hash_prefix=(short *) RelinquishMagickMemory(hash_prefix);
827+ hash_code=(short *) RelinquishMagickMemory(hash_code);
828+ packet=(unsigned char *) RelinquishMagickMemory(packet);
829+ return(MagickTrue);
830+}
831+
832
833+/*
834+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835+% %
836+% %
837+% %
838+% I s G I F %
839+% %
840+% %
841+% %
842+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843+%
844+% IsGIF() returns MagickTrue if the image format type, identified by the
845+% magick string, is GIF.
846+%
847+% The format of the IsGIF method is:
848+%
849+% MagickBooleanType IsGIF(const unsigned char *magick,const size_t length)
850+%
851+% A description of each parameter follows:
852+%
853+% o magick: compare image format pattern against these bytes.
854+%
855+% o length: Specifies the length of the magick string.
856+%
857+*/
858+static MagickBooleanType IsGIF(const unsigned char *magick,const size_t length)
859+{
860+ if (length < 4)
861+ return(MagickFalse);
862+ if (LocaleNCompare((char *) magick,"GIF8",4) == 0)
863+ return(MagickTrue);
864+ return(MagickFalse);
865+}
866+
867
868+/*
869+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870+% %
871+% %
872+% %
873++ R e a d B l o b B l o c k %
874+% %
875+% %
876+% %
877+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878+%
879+% ReadBlobBlock() reads data from the image file and returns it. The
880+% amount of data is determined by first reading a count byte. The number
881+% of bytes read is returned.
882+%
883+% The format of the ReadBlobBlock method is:
884+%
885+% size_t ReadBlobBlock(Image *image,unsigned char *data)
886+%
887+% A description of each parameter follows:
888+%
889+% o image: the image.
890+%
891+% o data: Specifies an area to place the information requested from
892+% the file.
893+%
894+*/
895+static ssize_t ReadBlobBlock(Image *image,unsigned char *data)
896+{
897+ ssize_t
898+ count;
899+
900+ unsigned char
901+ block_count;
902+
903+ assert(image != (Image *) NULL);
904+ assert(image->signature == MagickSignature);
905+ assert(data != (unsigned char *) NULL);
906+ count=ReadBlob(image,1,&block_count);
907+ if (count != 1)
908+ return(0);
909+ return(ReadBlob(image,(size_t) block_count,data));
910+}
911+
912
913+/*
914+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
915+% %
916+% %
917+% %
918+% R e a d G I F I m a g e %
919+% %
920+% %
921+% %
922+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
923+%
924+% ReadGIFImage() reads a Compuserve Graphics image file and returns it.
925+% It allocates the memory necessary for the new Image structure and returns a
926+% pointer to the new image.
927+%
928+% The format of the ReadGIFImage method is:
929+%
930+% Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
931+%
932+% A description of each parameter follows:
933+%
934+% o image_info: the image info.
935+%
936+% o exception: return any errors or warnings in this structure.
937+%
938+*/
939+
940+static inline size_t MagickMax(const size_t x,const size_t y)
941+{
942+ if (x > y)
943+ return(x);
944+ return(y);
945+}
946+
947+static inline size_t MagickMin(const size_t x,const size_t y)
948+{
949+ if (x < y)
950+ return(x);
951+ return(y);
952+}
953+
954+static MagickBooleanType PingGIFImage(Image *image)
955+{
956+ unsigned char
957+ buffer[256],
958+ length,
959+ data_size;
960+
961+ assert(image != (Image *) NULL);
962+ assert(image->signature == MagickSignature);
963+ if (image->debug != MagickFalse)
964+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
965+ if (ReadBlob(image,1,&data_size) != 1)
966+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
967+ if (data_size > MaximumLZWBits)
968+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
969+ if (ReadBlob(image,1,&length) != 1)
970+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
971+ while (length != 0)
972+ {
973+ if (ReadBlob(image,length,buffer) != (ssize_t) length)
974+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
975+ if (ReadBlob(image,1,&length) != 1)
976+ ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
977+ }
978+ return(MagickTrue);
979+}
980+
981+static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
982+{
983+#define BitSet(byte,bit) (((byte) & (bit)) == (bit))
984+#define LSBFirstOrder(x,y) (((y) << 8) | (x))
985+
986+ Image
987+ *image;
988+
989+ int
990+ number_extensionss=0;
991+
992+ MagickBooleanType
993+ status;
994+
995+ RectangleInfo
996+ page;
997+
998+ register ssize_t
999+ i;
1000+
1001+ register unsigned char
1002+ *p;
1003+
1004+ size_t
1005+ delay,
1006+ dispose,
1007+ global_colors,
1008+ image_count,
1009+ iterations,
1010+ one;
1011+
1012+ ssize_t
1013+ count,
1014+ opacity;
1015+
1016+ unsigned char
1017+ background,
1018+ c,
1019+ flag,
1020+ *global_colormap,
1021+ header[MaxTextExtent],
1022+ magick[12];
1023+
1024+ /*
1025+ Open image file.
1026+ */
1027+ assert(image_info != (const ImageInfo *) NULL);
1028+ assert(image_info->signature == MagickSignature);
1029+ if (image_info->debug != MagickFalse)
1030+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1031+ image_info->filename);
1032+ assert(exception != (ExceptionInfo *) NULL);
1033+ assert(exception->signature == MagickSignature);
1034+ image=AcquireImage(image_info);
1035+ status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1036+ if (status == MagickFalse)
1037+ {
1038+ image=DestroyImageList(image);
1039+ return((Image *) NULL);
1040+ }
1041+ /*
1042+ Determine if this a GIF file.
1043+ */
1044+ count=ReadBlob(image,6,magick);
1045+ if ((count != 6) || ((LocaleNCompare((char *) magick,"GIF87",5) != 0) &&
1046+ (LocaleNCompare((char *) magick,"GIF89",5) != 0)))
1047+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1048+ page.width=ReadBlobLSBShort(image);
1049+ page.height=ReadBlobLSBShort(image);
1050+ flag=(unsigned char) ReadBlobByte(image);
1051+ background=(unsigned char) ReadBlobByte(image);
1052+ c=(unsigned char) ReadBlobByte(image); /* reserved */
1053+ one=1;
1054+ global_colors=one << (((size_t) flag & 0x07)+1);
1055+ global_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1056+ MagickMax(global_colors,256),3UL*sizeof(*global_colormap));
1057+ if (global_colormap == (unsigned char *) NULL)
1058+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1059+ if (BitSet((int) flag,0x80) != 0)
1060+ count=ReadBlob(image,(size_t) (3*global_colors),global_colormap);
1061+ delay=0;
1062+ dispose=0;
1063+ iterations=1;
1064+ opacity=(-1);
1065+ image_count=0;
1066+ for ( ; ; )
1067+ {
1068+ count=ReadBlob(image,1,&c);
1069+ if (count != 1)
1070+ break;
1071+ if (c == (unsigned char) ';')
1072+ break; /* terminator */
1073+ if (c == (unsigned char) '!')
1074+ {
1075+ /*
1076+ GIF Extension block.
1077+ */
1078+
1079+ count=ReadBlob(image,1,&c);
1080+ if (count != 1)
1081+ {
1082+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1083+ global_colormap);
1084+ ThrowReaderException(CorruptImageError,
1085+ "UnableToReadExtensionBlock");
1086+ }
1087+ switch (c)
1088+ {
1089+ case 0xf9:
1090+ {
1091+ /*
1092+ Read graphics control extension.
1093+ */
1094+ while (ReadBlobBlock(image,header) != 0) ;
1095+ dispose=(size_t) (header[0] >> 2);
1096+ delay=(size_t) ((header[2] << 8) | header[1]);
1097+ if ((ssize_t) (header[0] & 0x01) == 0x01)
1098+ opacity=(ssize_t) header[3];
1099+ break;
1100+ }
1101+ case 0xfe:
1102+ {
1103+ char
1104+ *comments;
1105+
1106+ size_t
1107+ length;
1108+
1109+ /*
1110+ Read comment extension.
1111+ */
1112+ comments=AcquireString((char *) NULL);
1113+ for (length=0; ; length+=count)
1114+ {
1115+ count=(ssize_t) ReadBlobBlock(image,header);
1116+ if (count == 0)
1117+ break;
1118+ header[count]='\0';
1119+ comments=(char *) ResizeQuantumMemory(comments,length+count,
1120+ sizeof(*comments));
1121+ if (comments == (char *) NULL)
1122+ ThrowReaderException(ResourceLimitError,
1123+ "MemoryAllocationFailed");
1124+ (void) CopyMagickMemory(comments+length,header,(size_t) count);
1125+ }
1126+ comments[length+count]='\0';
1127+ (void) SetImageProperty(image,"comment",comments);
1128+ comments=DestroyString(comments);
1129+ break;
1130+ }
1131+ case 0xff:
1132+ {
1133+ MagickBooleanType
1134+ loop;
1135+
1136+ /*
1137+ Read Netscape Loop extension.
1138+ */
1139+ loop=MagickFalse;
1140+ if (ReadBlobBlock(image,header) != 0)
1141+ loop=LocaleNCompare((char *) header,"NETSCAPE2.0",11) == 0 ?
1142+ MagickTrue : MagickFalse;
1143+ if (loop != MagickFalse)
1144+ {
1145+ while (ReadBlobBlock(image,header) != 0)
1146+ iterations=(size_t) ((header[2] << 8) | header[1]);
1147+ break;
1148+ }
1149+ else
1150+ {
1151+ char
1152+ name[MaxTextExtent];
1153+
1154+ int
1155+ block_length,
1156+ info_length,
1157+ reserved_length;
1158+
1159+ MagickBooleanType
1160+ i8bim,
1161+ icc,
1162+ iptc,
1163+ magick;
1164+
1165+ StringInfo
1166+ *profile;
1167+
1168+ unsigned char
1169+ *info;
1170+
1171+ /*
1172+ Store GIF application extension as a generic profile.
1173+ */
1174+ icc=LocaleNCompare((char *) header,"ICCRGBG1012",11) == 0 ?
1175+ MagickTrue : MagickFalse;
1176+ magick=LocaleNCompare((char *) header,"ImageMagick",11) == 0 ?
1177+ MagickTrue : MagickFalse;
1178+ i8bim=LocaleNCompare((char *) header,"MGK8BIM0000",11) == 0 ?
1179+ MagickTrue : MagickFalse;
1180+ iptc=LocaleNCompare((char *) header,"MGKIPTC0000",11) == 0 ?
1181+ MagickTrue : MagickFalse;
1182+ number_extensionss++;
1183+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1184+ " Reading GIF application extension");
1185+ info=(unsigned char *) AcquireQuantumMemory(255UL,
1186+ sizeof(*info));
1187+ reserved_length=255;
1188+ for (info_length=0; ; )
1189+ {
1190+ block_length=(int) ReadBlobBlock(image,&info[info_length]);
1191+ if (block_length == 0)
1192+ break;
1193+ info_length+=block_length;
1194+ if (info_length > (reserved_length-255))
1195+ {
1196+ reserved_length+=4096;
1197+ info=(unsigned char *) ResizeQuantumMemory(info,
1198+ (size_t) reserved_length,sizeof(*info));
1199+ if (info == (unsigned char *) NULL)
1200+ ThrowReaderException(ResourceLimitError,
1201+ "MemoryAllocationFailed");
1202+ }
1203+ }
1204+ profile=BlobToStringInfo(info,(size_t) info_length);
1205+ if (profile == (StringInfo *) NULL)
1206+ ThrowReaderException(ResourceLimitError,
1207+ "MemoryAllocationFailed");
1208+ if (i8bim == MagickTrue)
1209+ (void) CopyMagickString(name,"8bim",sizeof(name));
1210+ else if (icc == MagickTrue)
1211+ (void) CopyMagickString(name,"icc",sizeof(name));
1212+ else if (iptc == MagickTrue)
1213+ (void) CopyMagickString(name,"iptc",sizeof(name));
1214+ else if (magick == MagickTrue)
1215+ {
1216+ (void) CopyMagickString(name,"magick",sizeof(name));
1217+ image->gamma=StringToDouble((char *) info+6,(char **) NULL);
1218+ }
1219+ else
1220+ (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
1221+ header);
1222+ info=(unsigned char *) RelinquishMagickMemory(info);
1223+ if (magick == MagickFalse)
1224+ (void) SetImageProfile(image,name,profile);
1225+ profile=DestroyStringInfo(profile);
1226+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1227+ " profile name=%s",name);
1228+ }
1229+ break;
1230+ }
1231+ default:
1232+ {
1233+ while (ReadBlobBlock(image,header) != 0) ;
1234+ break;
1235+ }
1236+ }
1237+ }
1238+ if (c != (unsigned char) ',')
1239+ continue;
1240+ if (image_count != 0)
1241+ {
1242+ /*
1243+ Allocate next image structure.
1244+ */
1245+ AcquireNextImage(image_info,image);
1246+ if (GetNextImageInList(image) == (Image *) NULL)
1247+ {
1248+ image=DestroyImageList(image);
1249+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1250+ global_colormap);
1251+ return((Image *) NULL);
1252+ }
1253+ image=SyncNextImageInList(image);
1254+ }
1255+ image_count++;
1256+ /*
1257+ Read image attributes.
1258+ */
1259+ image->storage_class=PseudoClass;
1260+ image->compression=LZWCompression;
1261+ page.x=(ssize_t) ReadBlobLSBShort(image);
1262+ page.y=(ssize_t) ReadBlobLSBShort(image);
1263+ image->columns=ReadBlobLSBShort(image);
1264+ image->rows=ReadBlobLSBShort(image);
1265+ image->depth=8;
1266+ flag=(unsigned char) ReadBlobByte(image);
1267+ image->interlace=BitSet((int) flag,0x40) != 0 ? GIFInterlace :
1268+ NoInterlace;
1269+ image->colors=BitSet((int) flag,0x80) == 0 ? global_colors :
1270+ one << ((size_t) (flag & 0x07)+1);
1271+ if (opacity >= (ssize_t) image->colors)
1272+ opacity=(-1);
1273+ image->page.width=page.width;
1274+ image->page.height=page.height;
1275+ image->page.y=page.y;
1276+ image->page.x=page.x;
1277+ image->delay=delay;
1278+ image->ticks_per_second=100;
1279+ image->dispose=(DisposeType) dispose;
1280+ image->iterations=iterations;
1281+ image->matte=opacity >= 0 ? MagickTrue : MagickFalse;
1282+ delay=0;
1283+ dispose=0;
1284+ iterations=1;
1285+ if ((image->columns == 0) || (image->rows == 0))
1286+ {
1287+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1288+ global_colormap);
1289+ ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
1290+ }
1291+ /*
1292+ Inititialize colormap.
1293+ */
1294+ if (AcquireImageColormap(image,image->colors) == MagickFalse)
1295+ {
1296+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1297+ global_colormap);
1298+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1299+ }
1300+ if (BitSet((int) flag,0x80) == 0)
1301+ {
1302+ /*
1303+ Use global colormap.
1304+ */
1305+ p=global_colormap;
1306+ for (i=0; i < (ssize_t) image->colors; i++)
1307+ {
1308+ image->colormap[i].red=ScaleCharToQuantum(*p++);
1309+ image->colormap[i].green=ScaleCharToQuantum(*p++);
1310+ image->colormap[i].blue=ScaleCharToQuantum(*p++);
1311+ if (i == opacity)
1312+ {
1313+ image->colormap[i].opacity=(Quantum) TransparentOpacity;
1314+ image->transparent_color=image->colormap[opacity];
1315+ }
1316+ }
1317+ image->background_color=image->colormap[MagickMin(background,
1318+ image->colors-1)];
1319+ }
1320+ else
1321+ {
1322+ unsigned char
1323+ *colormap;
1324+
1325+ /*
1326+ Read local colormap.
1327+ */
1328+ colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1329+ 3*sizeof(*colormap));
1330+ if (colormap == (unsigned char *) NULL)
1331+ {
1332+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1333+ global_colormap);
1334+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1335+ }
1336+ count=ReadBlob(image,(3*image->colors)*sizeof(*colormap),colormap);
1337+ if (count != (ssize_t) (3*image->colors))
1338+ {
1339+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1340+ global_colormap);
1341+ colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1342+ ThrowReaderException(CorruptImageError,
1343+ "InsufficientImageDataInFile");
1344+ }
1345+ p=colormap;
1346+ for (i=0; i < (ssize_t) image->colors; i++)
1347+ {
1348+ image->colormap[i].red=ScaleCharToQuantum(*p++);
1349+ image->colormap[i].green=ScaleCharToQuantum(*p++);
1350+ image->colormap[i].blue=ScaleCharToQuantum(*p++);
1351+ if (i == opacity)
1352+ image->colormap[i].opacity=(Quantum) TransparentOpacity;
1353+ }
1354+ colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1355+ }
1356+ if (image->gamma == 1.0)
1357+ {
1358+ for (i=0; i < (ssize_t) image->colors; i++)
1359+ if (IsGrayPixel(image->colormap+i) == MagickFalse)
1360+ break;
1361+ (void) SetImageColorspace(image,i == (ssize_t) image->colors ?
1362+ GRAYColorspace : RGBColorspace);
1363+ }
1364+ if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1365+ if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1366+ break;
1367+ /*
1368+ Decode image.
1369+ */
1370+ if (image_info->ping != MagickFalse)
1371+ status=PingGIFImage(image);
1372+ else
1373+ status=DecodeImage(image,opacity);
1374+ if ((image_info->ping == MagickFalse) && (status == MagickFalse))
1375+ {
1376+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1377+ global_colormap);
1378+ ThrowReaderException(CorruptImageError,"CorruptImage");
1379+ }
1380+ if (image_info->number_scenes != 0)
1381+ if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1382+ break;
1383+ opacity=(-1);
1384+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) image->scene-
1385+ 1,image->scene);
1386+ if (status == MagickFalse)
1387+ break;
1388+ }
1389+ global_colormap=(unsigned char *) RelinquishMagickMemory(global_colormap);
1390+ if ((image->columns == 0) || (image->rows == 0))
1391+ ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
1392+ (void) CloseBlob(image);
1393+ return(GetFirstImageInList(image));
1394+}
1395+
1396
1397+/*
1398+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1399+% %
1400+% %
1401+% %
1402+% R e g i s t e r G I F I m a g e %
1403+% %
1404+% %
1405+% %
1406+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407+%
1408+% RegisterGIFImage() adds properties for the GIF image format to
1409+% the list of supported formats. The properties include the image format
1410+% tag, a method to read and/or write the format, whether the format
1411+% supports the saving of more than one frame to the same file or blob,
1412+% whether the format supports native in-memory I/O, and a brief
1413+% description of the format.
1414+%
1415+% The format of the RegisterGIFImage method is:
1416+%
1417+% size_t RegisterGIFImage(void)
1418+%
1419+*/
1420+ModuleExport size_t RegisterGIFImage(void)
1421+{
1422+ MagickInfo
1423+ *entry;
1424+
1425+ entry=SetMagickInfo("GIF");
1426+ entry->decoder=(DecodeImageHandler *) ReadGIFImage;
1427+ entry->encoder=(EncodeImageHandler *) WriteGIFImage;
1428+ entry->magick=(IsImageFormatHandler *) IsGIF;
1429+ entry->description=ConstantString("CompuServe graphics interchange format");
1430+ entry->module=ConstantString("GIF");
1431+ (void) RegisterMagickInfo(entry);
1432+ entry=SetMagickInfo("GIF87");
1433+ entry->decoder=(DecodeImageHandler *) ReadGIFImage;
1434+ entry->encoder=(EncodeImageHandler *) WriteGIFImage;
1435+ entry->magick=(IsImageFormatHandler *) IsGIF;
1436+ entry->adjoin=MagickFalse;
1437+ entry->description=ConstantString("CompuServe graphics interchange format");
1438+ entry->version=ConstantString("version 87a");
1439+ entry->module=ConstantString("GIF");
1440+ (void) RegisterMagickInfo(entry);
1441+ return(MagickImageCoderSignature);
1442+}
1443+
1444
1445+/*
1446+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447+% %
1448+% %
1449+% %
1450+% U n r e g i s t e r G I F I m a g e %
1451+% %
1452+% %
1453+% %
1454+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1455+%
1456+% UnregisterGIFImage() removes format registrations made by the
1457+% GIF module from the list of supported formats.
1458+%
1459+% The format of the UnregisterGIFImage method is:
1460+%
1461+% UnregisterGIFImage(void)
1462+%
1463+*/
1464+ModuleExport void UnregisterGIFImage(void)
1465+{
1466+ (void) UnregisterMagickInfo("GIF");
1467+ (void) UnregisterMagickInfo("GIF87");
1468+}
1469+
1470
1471+/*
1472+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473+% %
1474+% %
1475+% %
1476+% W r i t e G I F I m a g e %
1477+% %
1478+% %
1479+% %
1480+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481+%
1482+% WriteGIFImage() writes an image to a file in the Compuserve Graphics
1483+% image format.
1484+%
1485+% The format of the WriteGIFImage method is:
1486+%
1487+% MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image)
1488+%
1489+% A description of each parameter follows.
1490+%
1491+% o image_info: the image info.
1492+%
1493+% o image: The image.
1494+%
1495+*/
1496+static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image)
1497+{
1498+ int
1499+ c;
1500+
1501+ ImageInfo
1502+ *write_info;
1503+
1504+ InterlaceType
1505+ interlace;
1506+
1507+ MagickBooleanType
1508+ status;
1509+
1510+ MagickOffsetType
1511+ scene;
1512+
1513+ RectangleInfo
1514+ page;
1515+
1516+ register ssize_t
1517+ i;
1518+
1519+ register unsigned char
1520+ *q;
1521+
1522+ size_t
1523+ bits_per_pixel,
1524+ delay,
1525+ length,
1526+ one;
1527+
1528+ ssize_t
1529+ j,
1530+ opacity;
1531+
1532+ unsigned char
1533+ *colormap,
1534+ *global_colormap;
1535+
1536+ /*
1537+ Open output image file.
1538+ */
1539+ assert(image_info != (const ImageInfo *) NULL);
1540+ assert(image_info->signature == MagickSignature);
1541+ assert(image != (Image *) NULL);
1542+ assert(image->signature == MagickSignature);
1543+ if (image->debug != MagickFalse)
1544+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1545+ status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1546+ if (status == MagickFalse)
1547+ return(status);
1548+ /*
1549+ Allocate colormap.
1550+ */
1551+ global_colormap=(unsigned char *) AcquireQuantumMemory(768UL,
1552+ sizeof(*global_colormap));
1553+ colormap=(unsigned char *) AcquireQuantumMemory(768UL,sizeof(*colormap));
1554+ if ((global_colormap == (unsigned char *) NULL) ||
1555+ (colormap == (unsigned char *) NULL))
1556+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1557+ for (i=0; i < 768; i++)
1558+ colormap[i]=(unsigned char) 0;
1559+ /*
1560+ Write GIF header.
1561+ */
1562+ write_info=CloneImageInfo(image_info);
1563+ if (LocaleCompare(write_info->magick,"GIF87") != 0)
1564+ (void) WriteBlob(image,6,(unsigned char *) "GIF89a");
1565+ else
1566+ {
1567+ (void) WriteBlob(image,6,(unsigned char *) "GIF87a");
1568+ write_info->adjoin=MagickFalse;
1569+ }
1570+ /*
1571+ Determine image bounding box.
1572+ */
1573+ page.width=image->columns;
1574+ if (image->page.width > page.width)
1575+ page.width=image->page.width;
1576+ page.height=image->rows;
1577+ if (image->page.height > page.height)
1578+ page.height=image->page.height;
1579+ page.x=image->page.x;
1580+ page.y=image->page.y;
1581+ (void) WriteBlobLSBShort(image,(unsigned short) page.width);
1582+ (void) WriteBlobLSBShort(image,(unsigned short) page.height);
1583+ /*
1584+ Write images to file.
1585+ */
1586+ interlace=write_info->interlace;
1587+ if ((write_info->adjoin != MagickFalse) &&
1588+ (GetNextImageInList(image) != (Image *) NULL))
1589+ interlace=NoInterlace;
1590+ scene=0;
1591+ one=1;
1592+ do
1593+ {
1594+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1595+ (void) TransformImageColorspace(image,sRGBColorspace);
1596+ opacity=(-1);
1597+ if (IsOpaqueImage(image,&image->exception) != MagickFalse)
1598+ {
1599+ if ((image->storage_class == DirectClass) || (image->colors > 256))
1600+ (void) SetImageType(image,PaletteType);
1601+ }
1602+ else
1603+ {
1604+ MagickRealType
1605+ alpha,
1606+ beta;
1607+
1608+ /*
1609+ Identify transparent colormap index.
1610+ */
1611+ if ((image->storage_class == DirectClass) || (image->colors > 256))
1612+ (void) SetImageType(image,PaletteBilevelMatteType);
1613+ for (i=0; i < (ssize_t) image->colors; i++)
1614+ if (image->colormap[i].opacity != OpaqueOpacity)
1615+ {
1616+ if (opacity < 0)
1617+ {
1618+ opacity=i;
1619+ continue;
1620+ }
1621+ alpha=(MagickRealType) TransparentOpacity-(MagickRealType)
1622+ image->colormap[i].opacity;
1623+ beta=(MagickRealType) TransparentOpacity-(MagickRealType)
1624+ image->colormap[opacity].opacity;
1625+ if (alpha < beta)
1626+ opacity=i;
1627+ }
1628+ if (opacity == -1)
1629+ {
1630+ (void) SetImageType(image,PaletteBilevelMatteType);
1631+ for (i=0; i < (ssize_t) image->colors; i++)
1632+ if (image->colormap[i].opacity != OpaqueOpacity)
1633+ {
1634+ if (opacity < 0)
1635+ {
1636+ opacity=i;
1637+ continue;
1638+ }
1639+ alpha=(Quantum) TransparentOpacity-(MagickRealType)
1640+ image->colormap[i].opacity;
1641+ beta=(Quantum) TransparentOpacity-(MagickRealType)
1642+ image->colormap[opacity].opacity;
1643+ if (alpha < beta)
1644+ opacity=i;
1645+ }
1646+ }
1647+ if (opacity >= 0)
1648+ {
1649+ image->colormap[opacity].red=image->transparent_color.red;
1650+ image->colormap[opacity].green=image->transparent_color.green;
1651+ image->colormap[opacity].blue=image->transparent_color.blue;
1652+ }
1653+ }
1654+ if ((image->storage_class == DirectClass) || (image->colors > 256))
1655+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1656+ for (bits_per_pixel=1; bits_per_pixel < 8; bits_per_pixel++)
1657+ if ((one << bits_per_pixel) >= image->colors)
1658+ break;
1659+ q=colormap;
1660+ for (i=0; i < (ssize_t) image->colors; i++)
1661+ {
1662+ *q++=ScaleQuantumToChar(image->colormap[i].red);
1663+ *q++=ScaleQuantumToChar(image->colormap[i].green);
1664+ *q++=ScaleQuantumToChar(image->colormap[i].blue);
1665+ }
1666+ for ( ; i < (ssize_t) (one << bits_per_pixel); i++)
1667+ {
1668+ *q++=(unsigned char) 0x0;
1669+ *q++=(unsigned char) 0x0;
1670+ *q++=(unsigned char) 0x0;
1671+ }
1672+ if ((GetPreviousImageInList(image) == (Image *) NULL) ||
1673+ (write_info->adjoin == MagickFalse))
1674+ {
1675+ /*
1676+ Write global colormap.
1677+ */
1678+ c=0x80;
1679+ c|=(8-1) << 4; /* color resolution */
1680+ c|=(bits_per_pixel-1); /* size of global colormap */
1681+ (void) WriteBlobByte(image,(unsigned char) c);
1682+ for (j=0; j < (ssize_t) image->colors; j++)
1683+ if (IsColorEqual(&image->background_color,image->colormap+j))
1684+ break;
1685+ (void) WriteBlobByte(image,(unsigned char)
1686+ (j == (ssize_t) image->colors ? 0 : j)); /* background color */
1687+ (void) WriteBlobByte(image,(unsigned char) 0x00); /* reserved */
1688+ length=(size_t) (3*(one << bits_per_pixel));
1689+ (void) WriteBlob(image,length,colormap);
1690+ for (j=0; j < 768; j++)
1691+ global_colormap[j]=colormap[j];
1692+ }
1693+ if (LocaleCompare(write_info->magick,"GIF87") != 0)
1694+ {
1695+ /*
1696+ Write graphics control extension.
1697+ */
1698+ (void) WriteBlobByte(image,(unsigned char) 0x21);
1699+ (void) WriteBlobByte(image,(unsigned char) 0xf9);
1700+ (void) WriteBlobByte(image,(unsigned char) 0x04);
1701+ c=image->dispose << 2;
1702+ if (opacity >= 0)
1703+ c|=0x01;
1704+ (void) WriteBlobByte(image,(unsigned char) c);
1705+ delay=(size_t) (100*image->delay/MagickMax((size_t)
1706+ image->ticks_per_second,1));
1707+ (void) WriteBlobLSBShort(image,(unsigned short) delay);
1708+ (void) WriteBlobByte(image,(unsigned char) (opacity >= 0 ? opacity :
1709+ 0));
1710+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1711+ if ((LocaleCompare(write_info->magick,"GIF87") != 0) &&
1712+ (GetImageProperty(image,"comment") != (const char *) NULL))
1713+ {
1714+ const char
1715+ *value;
1716+
1717+ register const char
1718+ *p;
1719+
1720+ size_t
1721+ count;
1722+
1723+ /*
1724+ Write comment extension.
1725+ */
1726+ (void) WriteBlobByte(image,(unsigned char) 0x21);
1727+ (void) WriteBlobByte(image,(unsigned char) 0xfe);
1728+ value=GetImageProperty(image,"comment");
1729+ for (p=value; *p != '\0'; )
1730+ {
1731+ count=MagickMin(strlen(p),255);
1732+ (void) WriteBlobByte(image,(unsigned char) count);
1733+ for (i=0; i < (ssize_t) count; i++)
1734+ (void) WriteBlobByte(image,(unsigned char) *p++);
1735+ }
1736+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1737+ }
1738+ if ((GetPreviousImageInList(image) == (Image *) NULL) &&
1739+ (GetNextImageInList(image) != (Image *) NULL) &&
1740+ (image->iterations != 1))
1741+ {
1742+ /*
1743+ Write Netscape Loop extension.
1744+ */
1745+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1746+ " Writing GIF Extension %s","NETSCAPE2.0");
1747+ (void) WriteBlobByte(image,(unsigned char) 0x21);
1748+ (void) WriteBlobByte(image,(unsigned char) 0xff);
1749+ (void) WriteBlobByte(image,(unsigned char) 0x0b);
1750+ (void) WriteBlob(image,11,(unsigned char *) "NETSCAPE2.0");
1751+ (void) WriteBlobByte(image,(unsigned char) 0x03);
1752+ (void) WriteBlobByte(image,(unsigned char) 0x01);
1753+ (void) WriteBlobLSBShort(image,(unsigned short) image->iterations);
1754+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1755+ }
1756+ if ((image->gamma != 1.0f/2.2f))
1757+ {
1758+ char
1759+ attributes[MaxTextExtent];
1760+
1761+ ssize_t
1762+ length;
1763+
1764+ /*
1765+ Write ImageMagick extension.
1766+ */
1767+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1768+ " Writing GIF Extension %s","ImageMagick");
1769+ (void) WriteBlobByte(image,(unsigned char) 0x21);
1770+ (void) WriteBlobByte(image,(unsigned char) 0xff);
1771+ (void) WriteBlobByte(image,(unsigned char) 0x0b);
1772+ (void) WriteBlob(image,11,(unsigned char *) "ImageMagick");
1773+ length=FormatLocaleString(attributes,MaxTextExtent,"gamma=%g",
1774+ image->gamma);
1775+ (void) WriteBlobByte(image,(unsigned char) length);
1776+ (void) WriteBlob(image,length,(unsigned char *) attributes);
1777+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1778+ }
1779+ ResetImageProfileIterator(image);
1780+ for ( ; ; )
1781+ {
1782+ char
1783+ *name;
1784+
1785+ const StringInfo
1786+ *profile;
1787+
1788+ name=GetNextImageProfile(image);
1789+ if (name == (const char *) NULL)
1790+ break;
1791+ profile=GetImageProfile(image,name);
1792+ if (profile != (StringInfo *) NULL)
1793+ {
1794+ if ((LocaleCompare(name,"ICC") == 0) ||
1795+ (LocaleCompare(name,"ICM") == 0) ||
1796+ (LocaleCompare(name,"IPTC") == 0) ||
1797+ (LocaleCompare(name,"8BIM") == 0) ||
1798+ (LocaleNCompare(name,"gif:",4) == 0))
1799+ {
1800+ size_t
1801+ length;
1802+
1803+ ssize_t
1804+ offset;
1805+
1806+ unsigned char
1807+ *datum;
1808+
1809+ datum=GetStringInfoDatum(profile);
1810+ length=GetStringInfoLength(profile);
1811+ (void) WriteBlobByte(image,(unsigned char) 0x21);
1812+ (void) WriteBlobByte(image,(unsigned char) 0xff);
1813+ (void) WriteBlobByte(image,(unsigned char) 0x0b);
1814+ if ((LocaleCompare(name,"ICC") == 0) ||
1815+ (LocaleCompare(name,"ICM") == 0))
1816+ {
1817+ /*
1818+ Write ICC extension.
1819+ */
1820+ (void) WriteBlob(image,11,(unsigned char *) "ICCRGBG1012");
1821+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1822+ " Writing GIF Extension %s","ICCRGBG1012");
1823+ }
1824+ else
1825+ if ((LocaleCompare(name,"IPTC") == 0))
1826+ {
1827+ /*
1828+ Write IPTC extension.
1829+ */
1830+ (void) WriteBlob(image,11,(unsigned char *) "MGKIPTC0000");
1831+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1832+ " Writing GIF Extension %s","MGKIPTC0000");
1833+ }
1834+ else
1835+ if ((LocaleCompare(name,"8BIM") == 0))
1836+ {
1837+ /*
1838+ Write 8BIM extension.
1839+ */
1840+ (void) WriteBlob(image,11,(unsigned char *)
1841+ "MGK8BIM0000");
1842+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1843+ " Writing GIF Extension %s","MGK8BIM0000");
1844+ }
1845+ else
1846+ {
1847+ char
1848+ extension[MaxTextExtent];
1849+
1850+ /*
1851+ Write generic extension.
1852+ */
1853+ (void) CopyMagickString(extension,name+4,
1854+ sizeof(extension));
1855+ (void) WriteBlob(image,11,(unsigned char *) extension);
1856+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1857+ " Writing GIF Extension %s",name);
1858+ }
1859+ offset=0;
1860+ while ((ssize_t) length > offset)
1861+ {
1862+ size_t
1863+ block_length;
1864+
1865+ if ((length-offset) < 255)
1866+ block_length=length-offset;
1867+ else
1868+ block_length=255;
1869+ (void) WriteBlobByte(image,(unsigned char) block_length);
1870+ (void) WriteBlob(image,(size_t) block_length,datum+offset);
1871+ offset+=(ssize_t) block_length;
1872+ }
1873+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1874+ }
1875+ }
1876+ }
1877+ }
1878+ (void) WriteBlobByte(image,','); /* image separator */
1879+ /*
1880+ Write the image header.
1881+ */
1882+ page.x=image->page.x;
1883+ page.y=image->page.y;
1884+ if ((image->page.width != 0) && (image->page.height != 0))
1885+ page=image->page;
1886+ (void) WriteBlobLSBShort(image,(unsigned short) (page.x < 0 ? 0 : page.x));
1887+ (void) WriteBlobLSBShort(image,(unsigned short) (page.y < 0 ? 0 : page.y));
1888+ (void) WriteBlobLSBShort(image,(unsigned short) image->columns);
1889+ (void) WriteBlobLSBShort(image,(unsigned short) image->rows);
1890+ c=0x00;
1891+ if (interlace != NoInterlace)
1892+ c|=0x40; /* pixel data is interlaced */
1893+ for (j=0; j < (ssize_t) (3*image->colors); j++)
1894+ if (colormap[j] != global_colormap[j])
1895+ break;
1896+ if (j == (ssize_t) (3*image->colors))
1897+ (void) WriteBlobByte(image,(unsigned char) c);
1898+ else
1899+ {
1900+ c|=0x80;
1901+ c|=(bits_per_pixel-1); /* size of local colormap */
1902+ (void) WriteBlobByte(image,(unsigned char) c);
1903+ length=(size_t) (3*(one << bits_per_pixel));
1904+ (void) WriteBlob(image,length,colormap);
1905+ }
1906+ /*
1907+ Write the image data.
1908+ */
1909+ c=(int) MagickMax(bits_per_pixel,2);
1910+ (void) WriteBlobByte(image,(unsigned char) c);
1911+ status=EncodeImage(write_info,image,(size_t) MagickMax(bits_per_pixel,2)+1);
1912+ if (status == MagickFalse)
1913+ {
1914+ global_colormap=(unsigned char *) RelinquishMagickMemory(
1915+ global_colormap);
1916+ colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1917+ write_info=DestroyImageInfo(write_info);
1918+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1919+ }
1920+ (void) WriteBlobByte(image,(unsigned char) 0x00);
1921+ if (GetNextImageInList(image) == (Image *) NULL)
1922+ break;
1923+ image=SyncNextImageInList(image);
1924+ scene++;
1925+ status=SetImageProgress(image,SaveImagesTag,scene,
1926+ GetImageListLength(image));
1927+ if (status == MagickFalse)
1928+ break;
1929+ } while (write_info->adjoin != MagickFalse);
1930+ (void) WriteBlobByte(image,';'); /* terminator */
1931+ global_colormap=(unsigned char *) RelinquishMagickMemory(global_colormap);
1932+ colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1933+ write_info=DestroyImageInfo(write_info);
1934+ (void) CloseBlob(image);
1935+ return(MagickTrue);
1936+}
1937
1938=== modified file '.pc/applied-patches'
1939--- .pc/applied-patches 2013-01-22 21:38:05 +0000
1940+++ .pc/applied-patches 2013-08-31 08:11:44 +0000
1941@@ -5,3 +5,4 @@
1942 0005-Memory-leak-after-setjmp-used-variable-need-to-be-vo.patch
1943 0006-Fix-a-memory-leak-in-webp-handling.patch
1944 0007-Magick-fix-a-memory-leak.patch
1945+0008-memory-corruption-while-processing-GIF-comments.patch
1946
1947=== modified file 'coders/gif.c'
1948--- coders/gif.c 2012-07-10 11:21:50 +0000
1949+++ coders/gif.c 2013-08-31 08:11:44 +0000
1950@@ -1100,14 +1100,17 @@
1951 if (count == 0)
1952 break;
1953 header[count]='\0';
1954+ (void) ConcatenateString(&comments,(const char *) header);
1955+ /*
1956 comments=(char *) ResizeQuantumMemory(comments,length+count,
1957 sizeof(*comments));
1958 if (comments == (char *) NULL)
1959 ThrowReaderException(ResourceLimitError,
1960 "MemoryAllocationFailed");
1961 (void) CopyMagickMemory(comments+length,header,(size_t) count);
1962+ */
1963 }
1964- comments[length+count]='\0';
1965+ /*comments[length+count]='\0';*/
1966 (void) SetImageProperty(image,"comment",comments);
1967 comments=DestroyString(comments);
1968 break;
1969
1970=== modified file 'debian/changelog'
1971--- debian/changelog 2013-02-24 18:06:30 +0000
1972+++ debian/changelog 2013-08-31 08:11:44 +0000
1973@@ -1,3 +1,10 @@
1974+imagemagick (8:6.7.7.10-5ubuntu3) saucy; urgency=low
1975+
1976+ * Add 0008-memory-corruption-while-processing-GIF-comments.patch
1977+ from debian experiemental and imagemagick upstream. lp:1218248
1978+
1979+ -- Jackson Doak <noskcaj@ubuntu.com> Sat, 31 Aug 2013 17:34:56 +1000
1980+
1981 imagemagick (8:6.7.7.10-5ubuntu2) raring; urgency=low
1982
1983 * libmagickcore-dev should depend on liblcms2-dev not liblcms-dev
1984
1985=== added file 'debian/patches/0008-memory-corruption-while-processing-GIF-comments.patch'
1986--- debian/patches/0008-memory-corruption-while-processing-GIF-comments.patch 1970-01-01 00:00:00 +0000
1987+++ debian/patches/0008-memory-corruption-while-processing-GIF-comments.patch 2013-08-31 08:11:44 +0000
1988@@ -0,0 +1,29 @@
1989+Memory corruption while processing GIF comments.
1990+
1991+It was a problem with handling comments. '\0' symbol was places after allocated memory buffer.
1992+To fix this problem raw memory handling functions was replaced with ConcatenateString.
1993+Original code that solves this problem: http://trac.imagemagick.org/changeset/8770/ImageMagick/trunk/coders/gif.c
1994+
1995+Index: imagemagick/coders/gif.c
1996+===================================================================
1997+--- imagemagick.orig/coders/gif.c 2013-08-31 17:34:12.641496415 +1000
1998++++ imagemagick/coders/gif.c 2013-08-31 17:34:12.605496236 +1000
1999+@@ -1100,14 +1100,17 @@
2000+ if (count == 0)
2001+ break;
2002+ header[count]='\0';
2003++ (void) ConcatenateString(&comments,(const char *) header);
2004++ /*
2005+ comments=(char *) ResizeQuantumMemory(comments,length+count,
2006+ sizeof(*comments));
2007+ if (comments == (char *) NULL)
2008+ ThrowReaderException(ResourceLimitError,
2009+ "MemoryAllocationFailed");
2010+ (void) CopyMagickMemory(comments+length,header,(size_t) count);
2011++ */
2012+ }
2013+- comments[length+count]='\0';
2014++ /*comments[length+count]='\0';*/
2015+ (void) SetImageProperty(image,"comment",comments);
2016+ comments=DestroyString(comments);
2017+ break;
2018
2019=== modified file 'debian/patches/series'
2020--- debian/patches/series 2013-01-22 21:38:05 +0000
2021+++ debian/patches/series 2013-08-31 08:11:44 +0000
2022@@ -6,3 +6,4 @@
2023 0005-Memory-leak-after-setjmp-used-variable-need-to-be-vo.patch
2024 0006-Fix-a-memory-leak-in-webp-handling.patch
2025 0007-Magick-fix-a-memory-leak.patch
2026+0008-memory-corruption-while-processing-GIF-comments.patch

Subscribers

People subscribed via source and target branches

to all changes: