256 lines
8.2 KiB
Diff
256 lines
8.2 KiB
Diff
Fix unsafe handling of DotRange and related tags. Back-port of upstream
|
|
patch for CVE-2012-5581. (Note: I have not pushed this into upstream CVS
|
|
for the 3.9 branch, because I'm not entirely convinced that it won't create
|
|
application compatibility issues --- tgl)
|
|
|
|
|
|
diff -Naur tiff-3.9.4.orig/libtiff/tif_dir.c tiff-3.9.4/libtiff/tif_dir.c
|
|
--- tiff-3.9.4.orig/libtiff/tif_dir.c 2010-06-09 17:15:27.000000000 -0400
|
|
+++ tiff-3.9.4/libtiff/tif_dir.c 2012-12-10 15:12:38.442326919 -0500
|
|
@@ -492,31 +492,28 @@
|
|
goto end;
|
|
}
|
|
|
|
- if ((fip->field_passcount
|
|
+ if (fip->field_tag == TIFFTAG_DOTRANGE
|
|
+ && strcmp(fip->field_name,"DotRange") == 0) {
|
|
+ /* TODO: This is an evil exception and should not have been
|
|
+ handled this way ... likely best if we move it into
|
|
+ the directory structure with an explicit field in
|
|
+ libtiff 4.1 and assign it a FIELD_ value */
|
|
+ uint16 v[2];
|
|
+ v[0] = (uint16)va_arg(ap, int);
|
|
+ v[1] = (uint16)va_arg(ap, int);
|
|
+ _TIFFmemcpy(tv->value, v, 4);
|
|
+ }
|
|
+ else if (fip->field_passcount
|
|
|| fip->field_writecount == TIFF_VARIABLE
|
|
|| fip->field_writecount == TIFF_VARIABLE2
|
|
|| fip->field_writecount == TIFF_SPP
|
|
- || tv->count > 1)
|
|
- && fip->field_tag != TIFFTAG_PAGENUMBER
|
|
- && fip->field_tag != TIFFTAG_HALFTONEHINTS
|
|
- && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
|
|
- && fip->field_tag != TIFFTAG_DOTRANGE) {
|
|
+ || tv->count > 1) {
|
|
_TIFFmemcpy(tv->value, va_arg(ap, void *),
|
|
tv->count * tv_size);
|
|
} else {
|
|
- /*
|
|
- * XXX: The following loop required to handle
|
|
- * TIFFTAG_PAGENUMBER, TIFFTAG_HALFTONEHINTS,
|
|
- * TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE tags.
|
|
- * These tags are actually arrays and should be passed as
|
|
- * array pointers to TIFFSetField() function, but actually
|
|
- * passed as a list of separate values. This behaviour
|
|
- * must be changed in the future!
|
|
- */
|
|
- int i;
|
|
char *val = (char *)tv->value;
|
|
|
|
- for (i = 0; i < tv->count; i++, val += tv_size) {
|
|
+ assert( tv->count == 1 );
|
|
switch (fip->field_type) {
|
|
case TIFF_BYTE:
|
|
case TIFF_UNDEFINED:
|
|
@@ -575,7 +572,6 @@
|
|
status = 0;
|
|
break;
|
|
}
|
|
- }
|
|
}
|
|
}
|
|
}
|
|
@@ -866,24 +862,27 @@
|
|
*va_arg(ap, uint16*) = (uint16)tv->count;
|
|
*va_arg(ap, void **) = tv->value;
|
|
ret_val = 1;
|
|
- } else {
|
|
- if ((fip->field_type == TIFF_ASCII
|
|
+ } else if (fip->field_tag == TIFFTAG_DOTRANGE
|
|
+ && strcmp(fip->field_name,"DotRange") == 0) {
|
|
+ /* TODO: This is an evil exception and should not have been
|
|
+ handled this way ... likely best if we move it into
|
|
+ the directory structure with an explicit field in
|
|
+ libtiff 4.1 and assign it a FIELD_ value */
|
|
+ *va_arg(ap, uint16*) = ((uint16 *)tv->value)[0];
|
|
+ *va_arg(ap, uint16*) = ((uint16 *)tv->value)[1];
|
|
+ ret_val = 1;
|
|
+ } else {
|
|
+ if (fip->field_type == TIFF_ASCII
|
|
|| fip->field_readcount == TIFF_VARIABLE
|
|
|| fip->field_readcount == TIFF_VARIABLE2
|
|
|| fip->field_readcount == TIFF_SPP
|
|
- || tv->count > 1)
|
|
- && fip->field_tag != TIFFTAG_PAGENUMBER
|
|
- && fip->field_tag != TIFFTAG_HALFTONEHINTS
|
|
- && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
|
|
- && fip->field_tag != TIFFTAG_DOTRANGE) {
|
|
+ || tv->count > 1) {
|
|
*va_arg(ap, void **) = tv->value;
|
|
ret_val = 1;
|
|
} else {
|
|
- int j;
|
|
char *val = (char *)tv->value;
|
|
|
|
- for (j = 0; j < tv->count;
|
|
- j++, val += _TIFFDataSize(tv->info->field_type)) {
|
|
+ assert( tv->count == 1 );
|
|
switch (fip->field_type) {
|
|
case TIFF_BYTE:
|
|
case TIFF_UNDEFINED:
|
|
@@ -933,7 +932,6 @@
|
|
ret_val = 0;
|
|
break;
|
|
}
|
|
- }
|
|
}
|
|
}
|
|
break;
|
|
diff -Naur tiff-3.9.4.orig/libtiff/tif_print.c tiff-3.9.4/libtiff/tif_print.c
|
|
--- tiff-3.9.4.orig/libtiff/tif_print.c 2010-06-08 14:50:42.000000000 -0400
|
|
+++ tiff-3.9.4/libtiff/tif_print.c 2012-12-10 15:41:42.860710914 -0500
|
|
@@ -112,16 +112,22 @@
|
|
}
|
|
|
|
static int
|
|
-_TIFFPrettyPrintField(TIFF* tif, FILE* fd, ttag_t tag,
|
|
+_TIFFPrettyPrintField(TIFF* tif, const TIFFFieldInfo *fip, FILE* fd, ttag_t tag,
|
|
uint32 value_count, void *raw_data)
|
|
{
|
|
TIFFDirectory *td = &tif->tif_dir;
|
|
|
|
+ /* do not try to pretty print auto-defined fields */
|
|
+ if (strncmp(fip->field_name,"Tag ", 4) == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
switch (tag)
|
|
{
|
|
case TIFFTAG_INKSET:
|
|
- fprintf(fd, " Ink Set: ");
|
|
- switch (*((uint16*)raw_data)) {
|
|
+ if (value_count == 2 && fip->field_type == TIFF_SHORT) {
|
|
+ fprintf(fd, " Ink Set: ");
|
|
+ switch (*((uint16*)raw_data)) {
|
|
case INKSET_CMYK:
|
|
fprintf(fd, "CMYK\n");
|
|
break;
|
|
@@ -130,15 +136,26 @@
|
|
*((uint16*)raw_data),
|
|
*((uint16*)raw_data));
|
|
break;
|
|
+ }
|
|
+ return 1;
|
|
}
|
|
- return 1;
|
|
+ return 0;
|
|
+
|
|
case TIFFTAG_DOTRANGE:
|
|
- fprintf(fd, " Dot Range: %u-%u\n",
|
|
- ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]);
|
|
- return 1;
|
|
+ if (value_count == 2 && fip->field_type == TIFF_SHORT) {
|
|
+ fprintf(fd, " Dot Range: %u-%u\n",
|
|
+ ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]);
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+
|
|
case TIFFTAG_WHITEPOINT:
|
|
- fprintf(fd, " White Point: %g-%g\n",
|
|
- ((float *)raw_data)[0], ((float *)raw_data)[1]); return 1;
|
|
+ if (value_count == 2 && fip->field_type == TIFF_RATIONAL) {
|
|
+ fprintf(fd, " White Point: %g-%g\n",
|
|
+ ((float *)raw_data)[0], ((float *)raw_data)[1]); return 1;
|
|
+ }
|
|
+ return 0;
|
|
+
|
|
case TIFFTAG_REFERENCEBLACKWHITE:
|
|
{
|
|
uint16 i;
|
|
@@ -178,10 +195,13 @@
|
|
(unsigned long) value_count);
|
|
return 1;
|
|
case TIFFTAG_STONITS:
|
|
- fprintf(fd,
|
|
- " Sample to Nits conversion factor: %.4e\n",
|
|
- *((double*)raw_data));
|
|
- return 1;
|
|
+ if (value_count == 1 && fip->field_type == TIFF_DOUBLE) {
|
|
+ fprintf(fd,
|
|
+ " Sample to Nits conversion factor: %.4e\n",
|
|
+ *((double*)raw_data));
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
|
|
return 0;
|
|
@@ -528,44 +548,28 @@
|
|
value_count = td->td_samplesperpixel;
|
|
else
|
|
value_count = fip->field_readcount;
|
|
- if ((fip->field_type == TIFF_ASCII
|
|
+ if (fip->field_tag == TIFFTAG_DOTRANGE
|
|
+ && strcmp(fip->field_name,"DotRange") == 0) {
|
|
+ /* TODO: This is an evil exception and should not have been
|
|
+ handled this way ... likely best if we move it into
|
|
+ the directory structure with an explicit field in
|
|
+ libtiff 4.1 and assign it a FIELD_ value */
|
|
+ static uint16 dotrange[2];
|
|
+ raw_data = dotrange;
|
|
+ TIFFGetField(tif, tag, dotrange+0, dotrange+1);
|
|
+ } else if (fip->field_type == TIFF_ASCII
|
|
|| fip->field_readcount == TIFF_VARIABLE
|
|
|| fip->field_readcount == TIFF_VARIABLE2
|
|
|| fip->field_readcount == TIFF_SPP
|
|
- || value_count > 1)
|
|
- && fip->field_tag != TIFFTAG_PAGENUMBER
|
|
- && fip->field_tag != TIFFTAG_HALFTONEHINTS
|
|
- && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
|
|
- && fip->field_tag != TIFFTAG_DOTRANGE) {
|
|
+ || value_count > 1) {
|
|
if(TIFFGetField(tif, tag, &raw_data) != 1)
|
|
continue;
|
|
- } else if (fip->field_tag != TIFFTAG_PAGENUMBER
|
|
- && fip->field_tag != TIFFTAG_HALFTONEHINTS
|
|
- && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
|
|
- && fip->field_tag != TIFFTAG_DOTRANGE) {
|
|
- raw_data = _TIFFmalloc(
|
|
- _TIFFDataSize(fip->field_type)
|
|
- * value_count);
|
|
- mem_alloc = 1;
|
|
- if(TIFFGetField(tif, tag, raw_data) != 1) {
|
|
- _TIFFfree(raw_data);
|
|
- continue;
|
|
- }
|
|
} else {
|
|
- /*
|
|
- * XXX: Should be fixed and removed, see the
|
|
- * notes related to TIFFTAG_PAGENUMBER,
|
|
- * TIFFTAG_HALFTONEHINTS,
|
|
- * TIFFTAG_YCBCRSUBSAMPLING and
|
|
- * TIFFTAG_DOTRANGE tags in tif_dir.c. */
|
|
- char *tmp;
|
|
raw_data = _TIFFmalloc(
|
|
_TIFFDataSize(fip->field_type)
|
|
* value_count);
|
|
- tmp = raw_data;
|
|
mem_alloc = 1;
|
|
- if(TIFFGetField(tif, tag, tmp,
|
|
- tmp + _TIFFDataSize(fip->field_type)) != 1) {
|
|
+ if(TIFFGetField(tif, tag, raw_data) != 1) {
|
|
_TIFFfree(raw_data);
|
|
continue;
|
|
}
|
|
@@ -578,7 +582,7 @@
|
|
* _TIFFPrettyPrintField() fall down and print it as any other
|
|
* tag.
|
|
*/
|
|
- if (_TIFFPrettyPrintField(tif, fd, tag, value_count, raw_data)) {
|
|
+ if (_TIFFPrettyPrintField(tif, fip, fd, tag, value_count, raw_data)) {
|
|
if(mem_alloc)
|
|
_TIFFfree(raw_data);
|
|
continue;
|