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

2009.11.29 17:02 "[Tiff] [PATCH 1/3] Make TIFFGetFieldDefaulted of WhitePoint 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_WHITEPOINT, the default result
is returned in a static buffer. If a multi-threaded program would
try to get the default value of WhitePoint, even with different TIFF*
objects, it would go wrong.

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

 libtiff/tif_aux.c     |   13 ++-----------
 libtiff/tif_dir.c     |   17 +++++++++++++++++
 libtiff/tif_dir.h     |    2 ++
 libtiff/tif_dirinfo.c |    2 +-
 libtiff/tif_print.c   |    7 +++----
 5 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c
index 560b5a4..149a95f 100644

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

@@ -201,17 +201,8 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap)

                *va_arg(ap, uint16 *) = td->td_ycbcrpositioning;

                return (1);
        case TIFFTAG_WHITEPOINT:

-

-                       whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
-                       whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);

+ return (1);
        case TIFFTAG_TRANSFERFUNCTION:
                if (!td->td_transferfunction[0] &&
                    !TIFFDefaultTransferFunction(td)) {
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 7e24622..6556cac 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -372,6 +372,9 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)

                td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, uint16_vap);
                td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, uint16_vap);
                break;
+       case TIFFTAG_WHITEPOINT:
+               _TIFFsetFloatArray(&td->td_whitepoint, va_arg(ap, float*), 2);
+               break;

        case TIFFTAG_TRANSFERFUNCTION:
                v = (td->td_samplesperpixel - td->td_extrasamples) > 1? 3: 1;
                for (i = 0; i < v; i++)
@@ -880,6 +883,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)

                        *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0];
                        *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1];
                        break;
+               case TIFFTAG_WHITEPOINT:
+                       *va_arg(ap, float**) = td->td_whitepoint;
+                       break;
                case TIFFTAG_TRANSFERFUNCTION:
                        *va_arg(ap, uint16**) = td->td_transferfunction[0];
                        if (td->td_samplesperpixel - td->td_extrasamples > 1) {

@@ -1075,6 +1081,7 @@ TIFFFreeDirectory(TIFF* tif)
        CleanupField(td_sampleinfo);
        CleanupField(td_subifd);
        CleanupField(td_inknames);

+       CleanupField(td_whitepoint);
        CleanupField(td_transferfunction[0]);
        CleanupField(td_transferfunction[1]);
        CleanupField(td_transferfunction[2]);
@@ -1156,6 +1163,16 @@ TIFFDefaultDirectory(TIFF* tif)
        td->td_ycbcrsubsampling[0] = 2;
        td->td_ycbcrsubsampling[1] = 2;
        td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
+
+       /* TIFF 6.0 specification tells that it is no default
+          value for the WhitePoint, but AdobePhotoshop TIFF
+          Technical Note tells that it should be CIE D50. */
+       td->td_whitepoint = (float *) _TIFFmalloc(2 * sizeof (float));
+       if (!td->td_whitepoint)
+               return 0;
+       td->td_whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
+       td->td_whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);
+
        tif->tif_postdecode = _TIFFNoPostDecode;  
        tif->tif_foundfield = NULL;
        tif->tif_tagmethods.vsetfield = _TIFFVSetField;  

diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index a0d333f..49e463e 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -81,6 +81,7 @@ typedef struct {

        uint16  td_ycbcrsubsampling[2];
        uint16  td_ycbcrpositioning;
        /* Colorimetry parameters */
+       float*  td_whitepoint;
        uint16* td_transferfunction[3];

        /* CMYK parameters */
        int td_inknameslen;
@@ -136,6 +137,7 @@ typedef struct {

 #define FIELD_HALFTONEHINTS            37
 #define FIELD_YCBCRSUBSAMPLING         39
 #define FIELD_YCBCRPOSITIONING         40
+#define FIELD_WHITEPOINT               42
 #define FIELD_TRANSFERFUNCTION         44
 #define FIELD_INKNAMES                 46
 #define FIELD_SUBIFD                   49
diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c

index fa4935a..b88fca7 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -87,7 +87,7 @@ tiffFields[] = {

{ TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL },

{ TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL },

{ TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL }, - { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL }, + { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_WHITEPOINT, 1, 0, "WhitePoint", NULL },

{ TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PrimaryChromaticities", NULL },

{ TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL },

{ TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL }, diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c

index 4b19964..10c1ece 100644
--- a/libtiff/tif_print.c
+++ b/libtiff/tif_print.c
@@ -159,10 +159,6 @@ _TIFFPrettyPrintField(TIFF* tif, FILE* fd, uint32 tag,
                        fprintf(fd, " Dot Range: %u-%u\n",
                            ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]);
                        return 1;

                case TIFFTAG_REFERENCEBLACKWHITE:
                {
                        uint16 i;
@@ -497,6 +493,9 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
                } else
                        fprintf(fd, "(present)\n");
        }
+ if (TIFFFieldSet(tif,FIELD_WHITEPOINT))
+ fprintf(fd, " White Point: %g-%g\n",
+ td->td_whitepoint[0], td->td_whitepoint[1]);
        if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
                fprintf(fd, " Transfer Function: ");
                if (flags & TIFFPRINT_CURVES) {
--
1.6.5.2