File GraphicsMagick-CVE-2016-7524.patch of Package GraphicsMagick.6323
ff -r 4f748e625c82 -r 8da95e3e5e81 coders/meta.c
Index: GraphicsMagick-1.3.21/coders/meta.c
===================================================================
--- GraphicsMagick-1.3.21.orig/coders/meta.c 2015-02-28 21:51:58.000000000 +0100
@@ -129,14 +129,16 @@ static unsigned int IsMETA(const unsigne
typedef struct _html_code
{
- short
+ unsigned short
len;
+
const char
*code,
val;
+
} html_code;
-static html_code html_codes[] = {
+static html_code const html_codes[] = {
#ifdef HANDLE_GT_LT
{ 4,"<",'<' },
{ 4,">",'>' },
@@ -179,29 +181,36 @@ static int stringnicmp(const char *p,con
return(toupper((int) *p)-toupper((int) *q));
}
-static int convertHTMLcodes(char *s, int len)
+static size_t convertHTMLcodes(char *s, const size_t len)
{
- if (len <=0 || s==(char*)NULL || *s=='\0')
+ int val;
+
+ if ((len == 0) || (s == (char*) NULL) || (*s=='\0'))
return 0;
- if (s[1] == '#')
- {
- int val, o;
+ /*
+ Check for hex or decimal character escape.
- if (sscanf(s,"&#%d;",&val) == 1)
- {
- o = 3;
- while (s[o] != ';')
+ e.g. hex: " ", decimal " "
+
+ Note that scanf is expected to parse the number in hex or decimal
+ and that it does not require the terminating ';' to appear in
+ order to parse the numeric argument.
+ */
+ if ((len > 3) && (s[1] == '#') && (strchr(s,';') != (char *) NULL) &&
+ (sscanf(s,"&#%d;",&val) == 1))
+ {
+ size_t o = 3;
+ while (s[o] != ';')
{
o++;
if (o > 5)
break;
}
- if (o < 6)
- (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
- *s = val;
- return o;
- }
+ if (o < 6)
+ (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+ *s = val;
+ return o;
}
else
{
@@ -281,10 +290,10 @@ static long parse8BIM(Image *ifile, Imag
char
brkused,
quoted,
- *line,
- *token,
- *newstr,
- *name;
+ *line = (char *) NULL,
+ *token = (char *) NULL,
+ *newstr = (char *) NULL,
+ *name = (char *) NULL;
int
state,
@@ -299,7 +308,7 @@ static long parse8BIM(Image *ifile, Imag
size_t
inputlen = BUFFER_SZ;
- long
+ ssize_t
savedolen = 0L,
outputlen = 0L;
@@ -313,7 +322,8 @@ static long parse8BIM(Image *ifile, Imag
dataset = 0;
recnum = 0;
line = MagickAllocateMemory(char *,inputlen);
- name = token = (char *)NULL;
+ if (line == (char *) NULL)
+ goto parse8BIM_failure;
savedpos = 0;
while(super_fgets(&line,&inputlen,ifile)!=NULL)
{
@@ -321,7 +331,11 @@ static long parse8BIM(Image *ifile, Imag
next=0;
token = MagickAllocateMemory(char *,inputlen);
+ if (token == (char *) NULL)
+ goto parse8BIM_failure;
newstr = MagickAllocateMemory(char *,inputlen);
+ if (newstr == (char *) NULL)
+ goto parse8BIM_failure;
while (Tokenizer(&token_info, 0, token, inputlen, line,
(char *) "", (char *) "=",
(char *) "\"", 0, &brkused,&next,"ed)==0)
@@ -354,8 +368,9 @@ static long parse8BIM(Image *ifile, Imag
break;
case 2:
name = MagickAllocateMemory(char *,strlen(newstr)+1);
- if (name)
- (void) strcpy(name,newstr);
+ if (name == (char *) NULL)
+ goto parse8BIM_failure;
+ (void) strcpy(name,newstr);
break;
}
state++;
@@ -367,7 +382,7 @@ static long parse8BIM(Image *ifile, Imag
int
next;
- unsigned long
+ size_t
len;
char
@@ -384,7 +399,7 @@ static long parse8BIM(Image *ifile, Imag
char
*s = &token[next-1];
- len -= convertHTMLcodes(s, (int) strlen(s));
+ len -= convertHTMLcodes(s, strlen(s));
}
}
@@ -400,6 +415,8 @@ static long parse8BIM(Image *ifile, Imag
{
long diff = outputlen - savedolen;
currentpos = TellBlob(ofile);
+ if (currentpos < 0)
+ goto parse8BIM_failure;
(void) SeekBlob(ofile,savedpos,SEEK_SET);
(void) WriteBlobMSBLong(ofile,diff);
(void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -433,7 +450,7 @@ static long parse8BIM(Image *ifile, Imag
next=0;
outputlen += len;
while (len--)
- (void) WriteBlobByte(ofile,token[next++]);
+ (void) WriteBlobByte(ofile,token[next++]); /* boom */
if (outputlen & 1)
{
@@ -445,6 +462,8 @@ static long parse8BIM(Image *ifile, Imag
{
/* patch in a fake length for now and fix it later */
savedpos = TellBlob(ofile);
+ if (savedpos < 0)
+ goto parse8BIM_failure;
(void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
outputlen += 4;
savedolen = outputlen;
@@ -478,12 +497,22 @@ static long parse8BIM(Image *ifile, Imag
long diff = outputlen - savedolen;
currentpos = TellBlob(ofile);
+ if (currentpos < 0)
+ goto parse8BIM_failure;
+
(void) SeekBlob(ofile,savedpos,SEEK_SET);
(void) WriteBlobMSBLong(ofile,diff);
(void) SeekBlob(ofile,currentpos,SEEK_SET);
savedolen = 0L;
}
return outputlen;
+
+ parse8BIM_failure:
+ MagickFreeMemory(token);
+ MagickFreeMemory(newstr);
+ MagickFreeMemory(name);
+ MagickFreeMemory(line);
+ return 0L;
}
static char *super_fgets_w(char **b, size_t *blen, Image *file)
@@ -542,10 +571,10 @@ static long parse8BIMW(Image *ifile, Ima
char
brkused,
quoted,
- *line,
- *token,
- *newstr,
- *name;
+ *line = (char *) NULL,
+ *token = (char *) NULL,
+ *newstr = (char *) NULL,
+ *name = (char *) NULL;
int
state,
@@ -560,7 +589,7 @@ static long parse8BIMW(Image *ifile, Ima
size_t
inputlen = BUFFER_SZ;
- long
+ ssize_t
savedolen = 0L,
outputlen = 0L;
@@ -574,6 +603,8 @@ static long parse8BIMW(Image *ifile, Ima
dataset = 0;
recnum = 0;
line = MagickAllocateMemory(char *,inputlen);
+ if (line == (char *) NULL)
+ goto parse8BIMW_failure;
name = token = (char *)NULL;
savedpos = 0;
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -586,7 +617,11 @@ static long parse8BIMW(Image *ifile, Ima
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"META CODER Parse8BIM: %s (%lu)",line, (unsigned long) inputlen);
token = MagickAllocateMemory(char *,inputlen);
+ if (token == (char *) NULL)
+ goto parse8BIMW_failure;
newstr = MagickAllocateMemory(char *,inputlen);
+ if (newstr == (char *) NULL)
+ goto parse8BIMW_failure;
while (Tokenizer(&token_info, 0, token, inputlen, line,
(char *) "", (char *) "=",
(char *) "\"", 0, &brkused,&next,"ed)==0)
@@ -619,8 +654,9 @@ static long parse8BIMW(Image *ifile, Ima
break;
case 2:
name = MagickAllocateMemory(char *,strlen(newstr)+1);
- if (name)
- (void) strcpy(name,newstr);
+ if (name == (char *) NULL)
+ goto parse8BIMW_failure;
+ (void) strcpy(name,newstr);
break;
}
state++;
@@ -632,7 +668,7 @@ static long parse8BIMW(Image *ifile, Ima
int
next;
- unsigned long
+ size_t
len;
char
@@ -649,7 +685,7 @@ static long parse8BIMW(Image *ifile, Ima
char
*s = &token[next-1];
- len -= convertHTMLcodes(s, (int) strlen(s));
+ len -= convertHTMLcodes(s, strlen(s));
}
}
@@ -665,6 +701,8 @@ static long parse8BIMW(Image *ifile, Ima
{
long diff = outputlen - savedolen;
currentpos = TellBlob(ofile);
+ if (currentpos < 0)
+ goto parse8BIMW_failure;
(void) SeekBlob(ofile,savedpos,SEEK_SET);
(void) WriteBlobMSBLong(ofile,diff);
(void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -710,6 +748,8 @@ static long parse8BIMW(Image *ifile, Ima
{
/* patch in a fake length for now and fix it later */
savedpos = TellBlob(ofile);
+ if (savedpos < 0)
+ goto parse8BIMW_failure;
(void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
outputlen += 4;
savedolen = outputlen;
@@ -743,12 +783,21 @@ static long parse8BIMW(Image *ifile, Ima
long diff = outputlen - savedolen;
currentpos = TellBlob(ofile);
+ if (currentpos < 0)
+ goto parse8BIMW_failure;
(void) SeekBlob(ofile,savedpos,SEEK_SET);
(void) WriteBlobMSBLong(ofile,diff);
(void) SeekBlob(ofile,currentpos,SEEK_SET);
savedolen = 0L;
}
return outputlen;
+
+ parse8BIMW_failure:
+ MagickFreeMemory(token);
+ MagickFreeMemory(newstr);
+ MagickFreeMemory(name);
+ MagickFreeMemory(line);
+ return 0L;
}
/* some defines for the different JPEG block types */
@@ -835,11 +884,12 @@ static int jpeg_skip_variable(Image *ifi
return 0;
}
-static int jpeg_skip_variable2(Image *ifile, Image *ARGUNUSED(ofile))
+static int jpeg_skip_variable2(Image *ifile, Image *ofile)
{
unsigned int length;
int c1,c2;
+ ARG_NOT_USED(ofile);
if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
@@ -908,8 +958,6 @@ static int jpeg_skip_till_marker(Image *
}
#endif
-static char psheader[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
-
/* Embed binary IPTC data into a JPEG image. */
static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
{
@@ -952,9 +1000,12 @@ static int jpeg_embed(Image *ifile, Imag
if (iptc != (Image *)NULL)
{
+ static const char psheader_base[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
+ char psheader[sizeof(psheader_base)];
len=GetBlobSize(iptc);
if (len & 1)
len++; /* make the length even */
+ (void) strlcpy(psheader,psheader_base,sizeof(psheader));
psheader[ 2 ] = (len+16)>>8;
psheader[ 3 ] = (len+16)&0xff;
for (inx = 0; inx < 18; inx++)
@@ -1250,7 +1301,7 @@ static Image *ReadMETAImage(const ImageI
DestroyImage(buff);
}
- if (LocaleCompare(image_info->magick,"IPTC") == 0)
+ if (LocaleNCompare(image_info->magick,"IPTC",4) == 0)
{
buff=AllocateImage((ImageInfo *) NULL);
if (buff == (Image *) NULL)
@@ -1260,7 +1311,7 @@ static Image *ReadMETAImage(const ImageI
{
DestroyImage(buff);
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
- image)
+ image);
}
AttachBlob(buff->blob,blob,length);
/* write out the header - length field patched below */
@@ -1286,14 +1337,21 @@ static Image *ReadMETAImage(const ImageI
}
/* subtract off the length of the 8BIM stuff */
+ blob=GetBlobStreamData(buff); /* blob may be realloced */
+ if ((blob == (const unsigned char *) NULL) || (GetBlobSize(buff) < 12))
+ {
+ DestroyImage(buff);
+ ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+ image);
+ }
length=GetBlobSize(buff)-12;
blob[10]=(unsigned char) ((length >> 8) & 0xff);
blob[11]=(unsigned char) (length & 0xff);
blob=GetBlobStreamData(buff);
length=GetBlobSize(buff);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- "Store IPTC profile, size %lu bytes",
- (unsigned long) length);
+ "Store IPTC profile, size %" MAGICK_SIZE_T_F
+ "u bytes",(MAGICK_SIZE_T) length);
(void) SetImageProfile(image,"IPTC",blob,length);
DetachBlob(buff->blob);
MagickFreeMemory(blob)
@@ -1840,9 +1898,14 @@ static int formatIPTC(Image *ifile, Imag
else
{
if (foundiptc)
- return -1;
+ {
+ return -1;
+ }
else
- continue;
+ {
+ c = ReadBlobByte(ifile);
+ continue;
+ }
}
/* we found the 0x1c tag and now grab the dataset and record number tags */
@@ -1888,7 +1951,11 @@ static int formatIPTC(Image *ifile, Imag
for (tagindx=0; tagindx<taglen; tagindx++)
{
c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
+ if (c == EOF)
+ {
+ MagickFreeMemory(str);
+ return -1;
+ }
str[tagindx] = (unsigned char) c;
}
str[taglen] = 0;
@@ -2011,7 +2078,11 @@ static int formatIPTCfromBuffer(Image *o
for (tagindx=0; tagindx<taglen; tagindx++)
{
c = *s++; len--;
- if (len < 0) return -1;
+ if (len < 0)
+ {
+ MagickFreeMemory(str);
+ return -1;
+ }
str[tagindx] = (unsigned char) c;
}
str[ taglen ] = 0;
@@ -2030,6 +2101,13 @@ static int formatIPTCfromBuffer(Image *o
return tagsfound;
}
+#define Format8BIMLiberate() \
+ do \
+ { \
+ MagickFreeMemory(PString); \
+ MagickFreeMemory(str); \
+ } while(0);
+
static int format8BIM(Image *ifile, Image *ofile)
{
char
@@ -2045,109 +2123,138 @@ static int format8BIM(Image *ifile, Imag
c;
unsigned char
- *PString,
- *str;
+ *PString=0,
+ *str=0;
resCount = 0;
c =ReadBlobByte(ifile);
while (c != EOF)
- {
- if (c == '8')
- {
- unsigned char
- buffer[5];
+ {
+ if (c == '8')
+ {
+ unsigned char
+ buffer[5];
- buffer[0] = (unsigned char) c;
- for (i=1; i<4; i++)
+ buffer[0] = (unsigned char) c;
+ for (i=1; i<4; i++)
+ {
+ c=ReadBlobByte(ifile);
+ if (c == EOF)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
+ buffer[i] = (unsigned char) c;
+ }
+ buffer[4] = 0;
+ if (strcmp((const char *)buffer, "8BIM") != 0)
+ continue;
+ }
+ else
{
c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
- buffer[i] = (unsigned char) c;
- }
- buffer[4] = 0;
- if (strcmp((const char *)buffer, "8BIM") != 0)
continue;
- }
- else
- {
- c=ReadBlobByte(ifile);
- continue;
- }
-
- /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
- ID = ReadBlobMSBShort(ifile);
- if (ID < 0) return -1;
- {
- unsigned char
- plen;
+ }
- c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
- plen = (unsigned char) c;
- PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
- if (PString == (unsigned char *) NULL)
- {
- (void) printf("MemoryAllocationFailed");
- return 0;
- }
- for (i=0; i<plen; i++)
- {
- c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
- PString[i] = (unsigned char) c;
- }
- PString[ plen ] = 0;
- if (!(plen&1))
- {
- c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
- }
- }
- Size = ReadBlobMSBLong(ifile);
- if (Size < 0) return -1;
- /* make a buffer to hold the data and snag it from the input stream */
- str=MagickAllocateMemory(unsigned char *,(size_t) Size);
- if (str == (unsigned char *) NULL)
+ /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
+ ID = ReadBlobMSBShort(ifile);
+ if (ID < 0)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
{
- (void) printf("MemoryAllocationFailed");
- return 0;
- }
- for (i=0; i<Size; i++)
- {
- c=ReadBlobByte(ifile);
- if (c == EOF) return -1;
- str[i] = (unsigned char) c;
- }
+ unsigned char
+ plen;
- /* we currently skip thumbnails, since it does not make
- * any sense preserving them in a real world application
- */
- if (ID != THUMBNAIL_ID)
- {
- /* now finish up by formatting this binary data into
- * ASCII equivalent
- */
- if (strlen((const char *) PString) != 0)
- FormatString(temp, "8BIM#%d#%s=", ID, PString);
- else
- FormatString(temp, "8BIM#%d=", ID);
- (void) WriteBlobString(ofile,temp);
- if (ID == IPTC_ID)
+ c=ReadBlobByte(ifile);
+ if (c == EOF)
{
- formatString(ofile, "IPTC", 4);
- (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+ Format8BIMLiberate();
+ return -1;
+ }
+ plen = (unsigned char) c;
+ PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
+ if (PString == (unsigned char *) NULL)
+ {
+ (void) printf("MemoryAllocationFailed");
+ Format8BIMLiberate();
+ return 0;
+ }
+ for (i=0; i<plen; i++)
+ {
+ c=ReadBlobByte(ifile);
+ if (c == EOF)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
+ PString[i] = (unsigned char) c;
+ }
+ PString[ plen ] = 0;
+ if (!(plen&1))
+ {
+ c=ReadBlobByte(ifile);
+ if (c == EOF)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
}
- else
- formatString(ofile, (char *)str, (long) Size);
}
- MagickFreeMemory(str);
- MagickFreeMemory(PString);
+ Size = ReadBlobMSBLong(ifile);
+ if (Size < 0)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
+ /* make a buffer to hold the data and snag it from the input stream */
+ str=MagickAllocateMemory(unsigned char *,(size_t) Size);
+ if (str == (unsigned char *) NULL)
+ {
+ (void) printf("MemoryAllocationFailed");
+ Format8BIMLiberate();
+ return 0;
+ }
+ for (i=0; i<Size; i++)
+ {
+ c=ReadBlobByte(ifile);
+ if (c == EOF)
+ {
+ Format8BIMLiberate();
+ return -1;
+ }
+ str[i] = (unsigned char) c;
+ }
+
+ /* we currently skip thumbnails, since it does not make
+ * any sense preserving them in a real world application
+ */
+ if (ID != THUMBNAIL_ID)
+ {
+ /* now finish up by formatting this binary data into
+ * ASCII equivalent
+ */
+ if (strlen((const char *) PString) != 0)
+ FormatString(temp, "8BIM#%d#%s=", ID, PString);
+ else
+ FormatString(temp, "8BIM#%d=", ID);
+ (void) WriteBlobString(ofile,temp);
+ if (ID == IPTC_ID)
+ {
+ formatString(ofile, "IPTC", 4);
+ (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+ }
+ else
+ formatString(ofile, (char *)str, (long) Size);
+ }
+ Format8BIMLiberate();
- resCount++;
+ resCount++;
- c=ReadBlobByte(ifile);
- }
+ c=ReadBlobByte(ifile);
+ }
return resCount;
}