2009.11.29 17:02 "[Tiff] Reentrancy patches", by Adam Goode

2009.11.29 17:02 "[Tiff] [PATCH 2/3] Make TIFFGetFieldDefaulted of ReferenceBlackWhite reentrant", by Adam Goode

When custom fields were introduced in 2005, many internal fields
were converted to use custom fields, and TIFFGetFieldDefaulted got
a bit more complicated each time (with TIFFDefaultDirectory

getting simpler). Unfortunately for TIFFTAG_REFERENCEBLACKWHITE, the

default result
is returned in a static buffer. If a multi-threaded program would
try to get the default value of

ReferenceBlackWhite, even with different TIFF* objects, it would
go wrong.

This fix returns ReferenceBlackWhite to a non-custom field, which
may not be perfect, but it does remove the static buffers.
---

 libtiff/tif_aux.c     |   60 +++++++++++++++++++++++++++----------------------
 libtiff/tif_dir.c     |    8 ++++++
 libtiff/tif_dir.h     |    2 +
 libtiff/tif_dirinfo.c |    2 +-
 4 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c

index 149a95f..e8d89f4 100644

--- a/libtiff/tif_aux.c
+++ b/libtiff/tif_aux.c

@@ -100,6 +100,35 @@ bad:
        return 0;
 }

+static int
+TIFFDefaultRefBlackWhite(TIFFDirectory* td)
+{
+       int i;
+
+       if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float))))
+               return 0;
+        if (td->td_photometric == PHOTOMETRIC_YCBCR) {
+               /*
+                * YCbCr (Class Y) images must have the ReferenceBlackWhite
+                * tag set. Fix the broken images, which lacks that tag.
+                */
+               td->td_refblackwhite[0] = 0.0F;
+               td->td_refblackwhite[1] = td->td_refblackwhite[3] =
+                       td->td_refblackwhite[5] = 255.0F;
+               td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F;
+       } else {
+               /*
+                * Assume RGB (Class R)
+                */
+               for (i = 0; i < 3; i++) {
+                   td->td_refblackwhite[2*i+0] = 0;
+                   td->td_refblackwhite[2*i+1] =
+                           (float)((1L<<td->td_bitspersample)-1L);
+               }
+       }
+       return 1;

+}
+
 /*

return (1);

                case TIFFTAG_REFERENCEBLACKWHITE:

-
- for (i = 0; i < 3; i++) {

-                               rgb_refblackwhite[2 * i + 0] = 0.0F;
-                               rgb_refblackwhite[2 * i + 1] =

-                               /*
-                                * YCbCr (Class Y) images must have the
-                                * ReferenceBlackWhite tag set. Fix the
-                                * broken images, which lacks that tag.
-                                */
-                               *va_arg(ap, float **) = ycbcr_refblackwhite;
-                       } else {
-                               /*
-                                * Assume RGB (Class R)
-                                */
-                               *va_arg(ap, float **) = rgb_refblackwhite;

- }

+               if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td))
+                       return (0);
+               *va_arg(ap, float **) = td->td_refblackwhite;
+               return (1);

        }
        return 0;
 }

diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c

index 6556cac..56863df 100644

--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c

@@ -381,6 +381,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
                        _TIFFsetShortArray(&td->td_transferfunction[i],
                            va_arg(ap, uint16*), 1L<<td->td_bitspersample);
                break;

+               /* XXX should check for null range */
+               _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
+               break;

        case TIFFTAG_INKNAMES:
                v = (uint16) va_arg(ap, uint16_vap);
                s = va_arg(ap, char*);
@@ -893,6 +897,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)

                                *va_arg(ap, uint16**) = td->td_transferfunction[2];

                        }
                        break;

+                       *va_arg(ap, float**) = td->td_refblackwhite;
+                       break;

                case TIFFTAG_INKNAMES:
                        *va_arg(ap, char**) = td->td_inknames;
                        break;
@@ -1082,6 +1089,7 @@ TIFFFreeDirectory(TIFF* tif)

        CleanupField(td_subifd);
        CleanupField(td_inknames);

+ CleanupField(td_refblackwhite);

        CleanupField(td_transferfunction[0]);
        CleanupField(td_transferfunction[1]);
        CleanupField(td_transferfunction[2]);

diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h

index 49e463e..70b68f2 100644

--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h

@@ -82,6 +82,7 @@ typedef struct {

        uint16  td_ycbcrpositioning;
        /* Colorimetry parameters */

+       float*  td_refblackwhite;

        uint16* td_transferfunction[3];

        /* CMYK parameters */
        int td_inknameslen;

@@ -137,6 +138,7 @@ typedef struct {

 #define FIELD_HALFTONEHINTS            37
 #define FIELD_YCBCRSUBSAMPLING         39
 #define FIELD_YCBCRPOSITIONING         40

+#define        FIELD_REFBLACKWHITE            41

diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c

index b88fca7..4a927aa 100644

--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c

@@ -112,7 +112,7 @@ tiffFields[] = {

{ TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL },

{ TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling", NULL },

{ TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning", NULL }, - { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ReferenceBlackWhite", NULL }, + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL },

{ TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "XMLPacket", NULL },

        /* begin SGI tags */

{ TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL },

--
1.6.5.2