File ImageMagick-security-dos.patch of Package ImageMagick.openSUSE_11.4_Update
http://www.imagemagick.org/discourse-server/viewtopic.php?f=4&t=20286 (note the date of announcement in contrast with date of patch)
Index: ImageMagick-6.6.5-8/magick/profile.c
===================================================================
--- ImageMagick-6.6.5-8.orig/magick/profile.c
+++ ImageMagick-6.6.5-8/magick/profile.c
@@ -1827,12 +1827,13 @@ MagickExport MagickBooleanType SyncImage
EndianType
endian;
- int
- offset;
+ SplayTreeInfo
+ *exif_resources;
ssize_t
id,
- level;
+ level,
+ offset;
size_t
entry,
@@ -1889,12 +1890,14 @@ MagickExport MagickBooleanType SyncImage
/*
This the offset to the first IFD.
*/
- offset=(int) ReadProfileLong(endian,exif+4);
- if ((size_t) offset >= length)
+ offset=(ssize_t) ((int) ReadProfileLong(endian,exif+4));
+ if ((offset < 0) || ((size_t) offset >= length))
return(MagickFalse);
directory=exif+offset;
level=0;
entry=0;
+ exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
+ (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
do
{
if (level > 0)
@@ -1924,6 +1927,9 @@ MagickExport MagickBooleanType SyncImage
number_bytes;
q=(unsigned char *) (directory+2+(12*entry));
+ if (GetValueFromSplayTree(exif_resources,q) == q)
+ break;
+ (void) AddValueToSplayTree(exif_resources,q,q);
tag_value=(ssize_t) ReadProfileShort(endian,q);
format=(ssize_t) ReadProfileShort(endian,q+2);
if ((format-1) >= EXIF_NUM_FORMATS)
@@ -1934,13 +1940,15 @@ MagickExport MagickBooleanType SyncImage
p=q+8;
else
{
- int
+ ssize_t
offset;
/*
The directory entry contains an offset.
*/
- offset=(int) ReadProfileLong(endian,q+8);
+ offset=(ssize_t) ((int) ReadProfileLong(endian,q+8));
+ if ((offset+number_bytes) < offset)
+ continue; /* prevent overflow */
if ((size_t) (offset+number_bytes) > length)
continue;
p=(unsigned char *) (exif+offset);
@@ -1949,28 +1957,25 @@ MagickExport MagickBooleanType SyncImage
{
case 0x011a:
{
- (void) WriteProfileLong(endian,(size_t)
- (image->x_resolution+0.5),p);
+ (void) WriteProfileLong(endian,(size_t) (image->x_resolution+0.5),p);
(void) WriteProfileLong(endian,1UL,p+4);
break;
}
case 0x011b:
{
- (void) WriteProfileLong(endian,(size_t)
- (image->y_resolution+0.5),p);
+ (void) WriteProfileLong(endian,(size_t) (image->y_resolution+0.5),p);
(void) WriteProfileLong(endian,1UL,p+4);
break;
}
case 0x0112:
{
- (void) WriteProfileShort(endian,(unsigned short)
- image->orientation,p);
+ (void) WriteProfileShort(endian,(unsigned short) image->orientation,
+ p);
break;
}
case 0x0128:
{
- (void) WriteProfileShort(endian,(unsigned short)
- (image->units+1),p);
+ (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
break;
}
default:
@@ -1978,11 +1983,11 @@ MagickExport MagickBooleanType SyncImage
}
if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
{
- size_t
+ ssize_t
offset;
- offset=(size_t) ReadProfileLong(endian,p);
- if ((offset < length) && (level < (MaxDirectoryStack-2)))
+ offset=(ssize_t) ((int) ReadProfileLong(endian,p));
+ if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
{
directory_stack[level].directory=directory;
entry++;
@@ -1993,9 +1998,9 @@ MagickExport MagickBooleanType SyncImage
level++;
if ((directory+2+(12*number_entries)) > (exif+length))
break;
- offset=(size_t) ReadProfileLong(endian,directory+2+(12*
- number_entries));
- if ((offset != 0) && (offset < length) &&
+ offset=(ssize_t) ((int) ReadProfileLong(endian,directory+2+(12*
+ number_entries)));
+ if ((offset != 0) && ((size_t) offset < length) &&
(level < (MaxDirectoryStack-2)))
{
directory_stack[level].directory=exif+offset;
@@ -2007,5 +2012,6 @@ MagickExport MagickBooleanType SyncImage
}
}
} while (level > 0);
+ exif_resources=DestroySplayTree(exif_resources);
return(MagickTrue);
}
Index: ImageMagick-6.6.5-8/magick/property.c
===================================================================
--- ImageMagick-6.6.5-8.orig/magick/property.c
+++ ImageMagick-6.6.5-8/magick/property.c
@@ -459,6 +459,13 @@ static inline ssize_t MagickMax(const ss
return(y);
}
+static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
+{
+ if (x < y)
+ return(x);
+ return(y);
+}
+
static inline int ReadPropertyByte(const unsigned char **p,size_t *length)
{
int
@@ -593,7 +600,7 @@ static MagickBooleanType Get8BIMProperty
continue;
if (ReadPropertyByte(&info,&length) != (unsigned char) 'M')
continue;
- id=(ssize_t) ReadPropertyMSBShort(&info,&length);
+ id=(ssize_t) ((int) ReadPropertyMSBShort(&info,&length));
if (id < (ssize_t) start)
continue;
if (id > (ssize_t) stop)
@@ -624,7 +631,7 @@ static MagickBooleanType Get8BIMProperty
No name match, scroll forward and try next.
*/
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
continue;
}
if ((*name == '#') && (sub_number != 1))
@@ -634,7 +641,7 @@ static MagickBooleanType Get8BIMProperty
*/
sub_number--;
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
continue;
}
/*
@@ -649,7 +656,7 @@ static MagickBooleanType Get8BIMProperty
(void) CopyMagickMemory(attribute,(char *) info,(size_t) count);
attribute[count]='\0';
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
if ((id <= 1999) || (id >= 2999))
(void) SetImageProperty((Image *) image,key,(const char *)
attribute);
@@ -789,7 +796,9 @@ static MagickBooleanType GetEXIFProperty
*directory;
size_t
- entry,
+ entry;
+
+ ssize_t
offset;
} DirectoryInfo;
@@ -1095,6 +1104,7 @@ static MagickBooleanType GetEXIFProperty
all,
id,
level,
+ tag_offset,
tag_value;
register ssize_t
@@ -1112,9 +1122,11 @@ static MagickBooleanType GetEXIFProperty
size_t
entry,
number_entries,
- tag_offset,
tag;
+ SplayTreeInfo
+ *exif_resources;
+
/*
If EXIF data exists, then try to parse the request for a tag.
*/
@@ -1225,7 +1237,7 @@ static MagickBooleanType GetEXIFProperty
}
if (length < 16)
return(MagickFalse);
- id=(ssize_t) ReadPropertyShort(LSBEndian,exif);
+ id=(ssize_t) ((int) ReadPropertyShort(LSBEndian,exif));
endian=LSBEndian;
if (id == 0x4949)
endian=LSBEndian;
@@ -1240,7 +1252,7 @@ static MagickBooleanType GetEXIFProperty
This the offset to the first IFD.
*/
offset=(int) ReadPropertyLong(endian,exif+4);
- if ((size_t) offset >= length)
+ if ((offset < 0) || (size_t) offset >= length)
return(MagickFalse);
/*
Set the pointer to the first IFD and follow it were it leads.
@@ -1249,6 +1261,8 @@ static MagickBooleanType GetEXIFProperty
level=0;
entry=0;
tag_offset=0;
+ exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
+ (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
do
{
/*
@@ -1264,7 +1278,7 @@ static MagickBooleanType GetEXIFProperty
/*
Determine how many entries there are in the current IFD.
*/
- number_entries=ReadPropertyShort(endian,directory);
+ number_entries=(size_t) ((int) ReadPropertyShort(endian,directory));
for ( ; entry < number_entries; entry++)
{
ssize_t
@@ -1280,9 +1294,12 @@ static MagickBooleanType GetEXIFProperty
size_t
format;
- q=(unsigned char *) (directory+2+(12*entry));
- tag_value=(ssize_t) (ReadPropertyShort(endian,q)+tag_offset);
- format=(size_t) ReadPropertyShort(endian,q+2);
+ q=(unsigned char *) (directory+(12*entry)+2);
+ if (GetValueFromSplayTree(exif_resources,q) == q)
+ break;
+ (void) AddValueToSplayTree(exif_resources,q,q);
+ tag_value=(ssize_t) ((int) ReadPropertyShort(endian,q)+tag_offset);
+ format=(size_t) ((int) ReadPropertyShort(endian,q+2));
if (format >= (sizeof(tag_bytes)/sizeof(*tag_bytes)))
break;
components=(int) ReadPropertyLong(endian,q+4);
@@ -1298,6 +1315,8 @@ static MagickBooleanType GetEXIFProperty
The directory entry contains an offset.
*/
offset=(int) ReadPropertyLong(endian,q+8);
+ if ((offset+number_bytes) < offset)
+ continue; /* prevent overflow */
if ((size_t) (offset+number_bytes) > length)
continue;
p=(unsigned char *) (exif+offset);
@@ -1335,7 +1354,7 @@ static MagickBooleanType GetEXIFProperty
case EXIF_FMT_ULONG:
{
EXIFMultipleValues(4,"%.20g",(double)
- ReadPropertyLong(endian,p1));
+ ((int) ReadPropertyLong(endian,p1)));
break;
}
case EXIF_FMT_SLONG:
@@ -1347,8 +1366,8 @@ static MagickBooleanType GetEXIFProperty
case EXIF_FMT_URATIONAL:
{
EXIFMultipleFractions(8,"%.20g/%.20g",(double)
- ReadPropertyLong(endian,p1),(double)
- ReadPropertyLong(endian,p1+4));
+ ((int) ReadPropertyLong(endian,p1)),(double)
+ ((int) ReadPropertyLong(endian,p1+4)));
break;
}
case EXIF_FMT_SRATIONAL:
@@ -1449,19 +1468,19 @@ static MagickBooleanType GetEXIFProperty
}
}
if ((tag_value == TAG_EXIF_OFFSET) ||
- (tag_value == TAG_INTEROP_OFFSET) ||
- (tag_value == TAG_GPS_OFFSET))
+ (tag_value == TAG_INTEROP_OFFSET) || (tag_value == TAG_GPS_OFFSET))
{
- size_t
+ ssize_t
offset;
- offset=(size_t) ReadPropertyLong(endian,p);
- if ((offset < length) && (level < (MaxDirectoryStack-2)))
+ offset=(ssize_t) ((int) ReadPropertyLong(endian,p));
+ if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
{
- size_t
+ ssize_t
tag_offset1;
- tag_offset1=(tag_value == TAG_GPS_OFFSET) ? 0x10000UL : 0UL;
+ tag_offset1=(ssize_t) ((tag_value == TAG_GPS_OFFSET) ? 0x10000 :
+ 0);
directory_stack[level].directory=directory;
entry++;
directory_stack[level].entry=entry;
@@ -1473,9 +1492,9 @@ static MagickBooleanType GetEXIFProperty
level++;
if ((directory+2+(12*number_entries)) > (exif+length))
break;
- offset=(size_t) ReadPropertyLong(endian,directory+2+(12*
- number_entries));
- if ((offset != 0) && (offset < length) &&
+ offset=(ssize_t) ((int) ReadPropertyLong(endian,directory+2+(12*
+ number_entries)));
+ if ((offset != 0) && ((size_t) offset < length) &&
(level < (MaxDirectoryStack-2)))
{
directory_stack[level].directory=exif+offset;
@@ -1488,6 +1507,7 @@ static MagickBooleanType GetEXIFProperty
}
}
} while (level > 0);
+ exif_resources=DestroySplayTree(exif_resources);
return(MagickTrue);
}
@@ -1629,7 +1649,7 @@ static char *TracePSClippath(const unsig
in_subpath=MagickFalse;
while (length > 0)
{
- selector=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ selector=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
switch (selector)
{
case 0:
@@ -1638,15 +1658,15 @@ static char *TracePSClippath(const unsig
if (knot_count != 0)
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
Expected subpath length record.
*/
- knot_count=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ knot_count=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
blob+=22;
- length-=22;
+ length-=MagickMin(22,(ssize_t) length);
break;
}
case 1:
@@ -1660,7 +1680,7 @@ static char *TracePSClippath(const unsig
Unexpected subpath knot
*/
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
@@ -1672,8 +1692,8 @@ static char *TracePSClippath(const unsig
xx,
yy;
- yy=ReadPropertyMSBLong(&blob,&length);
- xx=ReadPropertyMSBLong(&blob,&length);
+ yy=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
+ xx=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
x=(ssize_t) xx;
if (xx > 2147483647)
x=(ssize_t) xx-4294967295-1;
@@ -1761,7 +1781,7 @@ static char *TracePSClippath(const unsig
default:
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
}
@@ -1826,7 +1846,7 @@ static char *TraceSVGClippath(const unsi
in_subpath=MagickFalse;
while (length != 0)
{
- selector=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ selector=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
switch (selector)
{
case 0:
@@ -1835,15 +1855,15 @@ static char *TraceSVGClippath(const unsi
if (knot_count != 0)
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
Expected subpath length record.
*/
- knot_count=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ knot_count=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
blob+=22;
- length-=22;
+ length-=MagickMin(22,(ssize_t) length);
break;
}
case 1:
@@ -1857,7 +1877,7 @@ static char *TraceSVGClippath(const unsi
Unexpected subpath knot.
*/
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
@@ -1932,7 +1952,7 @@ static char *TraceSVGClippath(const unsi
default:
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
}