summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-11-10 17:27:08 +0100
committerEven Rouault <even.rouault@spatialys.com>2022-11-21 23:21:13 +0100
commit91e95ee9ae9cc91b5e657cb078827c361da9b1ae (patch)
tree91a4bf83b281ea92793504a6fdb4d0e532b032dc
parente7e567536baddd491e124f6fc5e11e80e740934e (diff)
downloadlibtiff-git-91e95ee9ae9cc91b5e657cb078827c361da9b1ae.tar.gz
Add TIFFOpenExt(), TIFFOpenWExt() and TIFFFdOpenExt() with re-entrant error handlers
Rename TIFFClientOpenEx() to TIFFClientOpenExt() Rework signature of the re-entrant error handlers and of TIFFSetWarningHandlerExt() and TIFFSetErrorHandlerExt() Use structures that can be extended as extra argument. Leverages and ammends https://gitlab.com/libtiff/libtiff/-/merge_requests/409
-rw-r--r--libtiff/libtiff.def9
-rw-r--r--libtiff/libtiff.map9
-rw-r--r--libtiff/tif_error.c9
-rw-r--r--libtiff/tif_open.c55
-rw-r--r--libtiff/tif_unix.c99
-rw-r--r--libtiff/tif_warning.c9
-rw-r--r--libtiff/tif_win32.c98
-rw-r--r--libtiff/tiffio.h50
-rw-r--r--libtiff/tiffiop.h5
-rw-r--r--test/CMakeLists.txt5
-rw-r--r--test/Makefile.am4
-rw-r--r--test/test_error_handlers.c151
12 files changed, 450 insertions, 53 deletions
diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def
index ee5486a6..2555a176 100644
--- a/libtiff/libtiff.def
+++ b/libtiff/libtiff.def
@@ -5,7 +5,7 @@ EXPORTS TIFFAccessTagMethods
TIFFCheckpointDirectory
TIFFCleanup
TIFFClientOpen
- TIFFClientOpenEx
+ TIFFClientOpenExt
TIFFClientdata
TIFFClose
TIFFComputeStrip
@@ -25,7 +25,9 @@ EXPORTS TIFFAccessTagMethods
TIFFDeferStrileArrayWriting
TIFFError
TIFFErrorExt
+ TIFFErrorExtR
TIFFFdOpen
+ TIFFFdOpenExt
TIFFFieldDataType
TIFFFieldName
TIFFFieldPassCount
@@ -78,7 +80,9 @@ EXPORTS TIFFAccessTagMethods
TIFFNumberOfStrips
TIFFNumberOfTiles
TIFFOpen
+ TIFFOpenExt
TIFFOpenW
+ TIFFOpenWExt
TIFFPrintDirectory
TIFFRGBAImageBegin
TIFFRGBAImageEnd
@@ -117,6 +121,7 @@ EXPORTS TIFFAccessTagMethods
TIFFSetDirectory
TIFFSetErrorHandler
TIFFSetErrorHandlerExt
+ TIFFSetErrorHandlerExtR
TIFFSetField
TIFFSetFileName
TIFFSetFileno
@@ -125,6 +130,7 @@ EXPORTS TIFFAccessTagMethods
TIFFSetTagExtender
TIFFSetWarningHandler
TIFFSetWarningHandlerExt
+ TIFFSetWarningHandlerExtR
TIFFSetWriteOffset
TIFFSetupStrips
TIFFStripSize
@@ -156,6 +162,7 @@ EXPORTS TIFFAccessTagMethods
TIFFVTileSize64
TIFFWarning
TIFFWarningExt
+ TIFFWarningExtR
TIFFWriteBufferSetup
TIFFWriteCheck
TIFFWriteCustomDirectory
diff --git a/libtiff/libtiff.map b/libtiff/libtiff.map
index 4c66ed41..39afafac 100644
--- a/libtiff/libtiff.map
+++ b/libtiff/libtiff.map
@@ -202,5 +202,12 @@ LIBTIFF_4.4 {
LIBTIFF_4.5 {
_TIFFClampDoubleToUInt32;
- TIFFClientOpenEx;
+ TIFFClientOpenExt;
+ TIFFFdOpenExt;
+ TIFFOpenExt;
+ TIFFOpenWExt;
+ TIFFErrorExtR;
+ TIFFWarningExtR;
+ TIFFSetErrorHandlerExtR;
+ TIFFSetWarningHandlerExtR;
} LIBTIFF_4.4;
diff --git a/libtiff/tif_error.c b/libtiff/tif_error.c
index 2bd74d52..000654e0 100644
--- a/libtiff/tif_error.c
+++ b/libtiff/tif_error.c
@@ -77,8 +77,11 @@ TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...)
}
}
-void TIFFSetErrorHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) {
- if (tif) tif->tif_errorhandler = handler;
+void TIFFSetErrorHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler, void* errorhandler_user_data) {
+ if (tif) {
+ tif->tif_errorhandler_user_data = errorhandler_user_data;
+ tif->tif_errorhandler = handler;
+ }
}
void TIFFErrorExtR(TIFF* tif, const char* module, const char* fmt, ...)
@@ -86,7 +89,7 @@ void TIFFErrorExtR(TIFF* tif, const char* module, const char* fmt, ...)
va_list ap;
if (tif && tif->tif_errorhandler) {
va_start(ap, fmt);
- int stop = (*tif->tif_errorhandler)(tif->tif_clientdata, module, fmt, ap);
+ int stop = (*tif->tif_errorhandler)(tif, tif->tif_errorhandler_user_data, module, fmt, ap);
va_end(ap);
if (stop) return;
}
diff --git a/libtiff/tif_open.c b/libtiff/tif_open.c
index c16a5e66..f95f5163 100644
--- a/libtiff/tif_open.c
+++ b/libtiff/tif_open.c
@@ -79,29 +79,52 @@ TIFFClientOpen(
TIFFMapFileProc mapproc,
TIFFUnmapFileProc unmapproc
) {
- return TIFFClientOpenEx(name, mode, clientdata, readproc, writeproc, seekproc, closeproc,
- sizeproc, mapproc, unmapproc, NULL, NULL);
+ TIFFClientOpenExtStruct arguments = {
+ .version = 1,
+ .readproc = readproc,
+ .writeproc = writeproc,
+ .seekproc = seekproc,
+ .closeproc = closeproc,
+ .sizeproc = sizeproc,
+ .mapproc = mapproc,
+ .unmapproc = unmapproc,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFClientOpenExt(name, mode, clientdata, &arguments);
}
TIFF*
-TIFFClientOpenEx(
+TIFFClientOpenExt(
const char* name, const char* mode,
thandle_t clientdata,
- TIFFReadWriteProc readproc,
- TIFFReadWriteProc writeproc,
- TIFFSeekProc seekproc,
- TIFFCloseProc closeproc,
- TIFFSizeProc sizeproc,
- TIFFMapFileProc mapproc,
- TIFFUnmapFileProc unmapproc,
- TIFFErrorHandlerExtR errorhandler,
- TIFFErrorHandlerExtR warnhandler)
+ TIFFClientOpenExtStruct* arguments)
{
- static const char module[] = "TIFFClientOpenEx";
+ static const char module[] = "TIFFClientOpenExt";
TIFF *tif;
int m;
const char* cp;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(clientdata, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(clientdata, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+ TIFFReadWriteProc readproc = arguments->readproc;
+ TIFFReadWriteProc writeproc = arguments->writeproc;
+ TIFFSeekProc seekproc = arguments->seekproc;
+ TIFFCloseProc closeproc = arguments->closeproc;
+ TIFFSizeProc sizeproc = arguments->sizeproc;
+ TIFFMapFileProc mapproc = arguments->mapproc;
+ TIFFUnmapFileProc unmapproc = arguments->unmapproc;
+
/* The following are configuration checks. They should be redundant, but should not
* compile to any actual code in an optimised release build anyway. If any of them
* fail, (makefile-based or other) configuration is not correct */
@@ -152,8 +175,10 @@ TIFFClientOpenEx(
tif->tif_sizeproc = sizeproc;
tif->tif_mapproc = mapproc ? mapproc : _tiffDummyMapProc;
tif->tif_unmapproc = unmapproc ? unmapproc : _tiffDummyUnmapProc;
- tif->tif_errorhandler = errorhandler;
- tif->tif_warnhandler = warnhandler;
+ tif->tif_errorhandler = arguments->errorhandler;
+ tif->tif_errorhandler_user_data = arguments->errorhandler_user_data;
+ tif->tif_warnhandler = arguments->warnhandler;
+ tif->tif_warnhandler_user_data = arguments->warnhandler_user_data;
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
TIFFErrorExtR(tif, module,
diff --git a/libtiff/tif_unix.c b/libtiff/tif_unix.c
index cb543542..34ad36c8 100644
--- a/libtiff/tif_unix.c
+++ b/libtiff/tif_unix.c
@@ -202,15 +202,51 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
TIFF*
TIFFFdOpen(int fd, const char* name, const char* mode)
{
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFFdOpenExt(fd, name, mode, &arguments);
+}
+
+TIFF*
+TIFFFdOpenExt(int fd, const char* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
+ static const char module[] = "TIFFFdOpenExt";
TIFF* tif;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+ TIFFClientOpenExtStruct client_arguments = {
+ .version = 1,
+ .readproc = _tiffReadProc,
+ .writeproc = _tiffWriteProc,
+ .seekproc = _tiffSeekProc,
+ .closeproc = _tiffCloseProc,
+ .sizeproc = _tiffSizeProc,
+ .mapproc = _tiffMapProc,
+ .unmapproc = _tiffUnmapProc,
+ .errorhandler = arguments->errorhandler,
+ .errorhandler_user_data = arguments->errorhandler_user_data,
+ .warnhandler = arguments->warnhandler,
+ .warnhandler_user_data = arguments->warnhandler_user_data
+ };
+
fd_as_handle_union_t fdh;
fdh.fd = fd;
- tif = TIFFClientOpen(name, mode,
- fdh.h,
- _tiffReadProc, _tiffWriteProc,
- _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
- _tiffMapProc, _tiffUnmapProc);
+ tif = TIFFClientOpenExt(name, mode,
+ fdh.h, &client_arguments);
if (tif)
tif->tif_fd = fd;
return (tif);
@@ -222,10 +258,34 @@ TIFFFdOpen(int fd, const char* name, const char* mode)
TIFF*
TIFFOpen(const char* name, const char* mode)
{
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFOpenExt(name, mode, &arguments);
+}
+
+TIFF*
+TIFFOpenExt(const char* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
static const char module[] = "TIFFOpen";
int m, fd;
TIFF* tif;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+
m = _TIFFgetMode(mode, module);
if (m == -1)
return ((TIFF*)0);
@@ -245,7 +305,7 @@ TIFFOpen(const char* name, const char* mode)
return ((TIFF *)0);
}
- tif = TIFFFdOpen((int)fd, name, mode);
+ tif = TIFFFdOpenExt((int)fd, name, mode, arguments);
if(!tif)
close(fd);
return tif;
@@ -259,12 +319,35 @@ TIFFOpen(const char* name, const char* mode)
TIFF*
TIFFOpenW(const wchar_t* name, const char* mode)
{
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFOpenWEx(name, mode, &arguments);
+}
+TIFF*
+TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
static const char module[] = "TIFFOpenW";
int m, fd;
int mbsize;
char *mbname;
TIFF* tif;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+
m = _TIFFgetMode(mode, module);
if (m == -1)
return ((TIFF*)0);
@@ -294,8 +377,8 @@ TIFFOpenW(const wchar_t* name, const char* mode)
NULL, NULL);
}
- tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "<unknown>",
- mode);
+ tif = TIFFFdOpenExt((int)fd, (mbname != NULL) ? mbname : "<unknown>",
+ mode, arguments);
_TIFFfree(mbname);
diff --git a/libtiff/tif_warning.c b/libtiff/tif_warning.c
index aa26faca..d952bdfd 100644
--- a/libtiff/tif_warning.c
+++ b/libtiff/tif_warning.c
@@ -77,8 +77,11 @@ TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...)
}
}
-void TIFFSetWarningHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) {
- if (tif) tif->tif_warnhandler = handler;
+void TIFFSetWarningHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler, void* warnhandler_user_data) {
+ if (tif) {
+ tif->tif_warnhandler_user_data = warnhandler_user_data;
+ tif->tif_warnhandler = handler;
+ }
}
void TIFFWarningExtR(TIFF* tif, const char* module, const char* fmt, ...)
@@ -86,7 +89,7 @@ void TIFFWarningExtR(TIFF* tif, const char* module, const char* fmt, ...)
va_list ap;
if (tif && tif->tif_warnhandler) {
va_start(ap, fmt);
- int stop = (*tif->tif_warnhandler)(tif->tif_clientdata, module, fmt, ap);
+ int stop = (*tif->tif_warnhandler)(tif, tif->tif_warnhandler_user_data, module, fmt, ap);
va_end(ap);
if (stop) return;
}
diff --git a/libtiff/tif_win32.c b/libtiff/tif_win32.c
index d617a0f4..2e62f080 100644
--- a/libtiff/tif_win32.c
+++ b/libtiff/tif_win32.c
@@ -232,9 +232,32 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
TIFF*
TIFFFdOpen(int ifd, const char* name, const char* mode)
{
+ TIFFOpenExtStruct arguments;
+ arguments.version = 1;
+ arguments.errorhandler = NULL;
+ arguments.warnhandler = NULL;
+ return TIFFFdOpenExt(ifd, name, mode, &arguments);
+}
+
+TIFF*
+TIFFFdOpenExt(int ifd, const char* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
+ static const char module[] = "TIFFFdOpenExt";
TIFF* tif;
int fSuppressMap;
int m;
+
+ if( arguments == NULL )
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if( arguments->version < 1 )
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+
fSuppressMap=0;
for (m=0; mode[m]!=0; m++)
{
@@ -244,11 +267,21 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
break;
}
}
- tif = TIFFClientOpen(name, mode, thandle_from_int(ifd),
- _tiffReadProc, _tiffWriteProc,
- _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
- fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
- fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
+
+ TIFFClientOpenExtStruct client_arguments;
+ client_arguments.version = 1;
+ client_arguments.readproc = _tiffReadProc;
+ client_arguments.writeproc = _tiffWriteProc;
+ client_arguments.seekproc = _tiffSeekProc;
+ client_arguments.closeproc = _tiffCloseProc;
+ client_arguments.sizeproc = _tiffSizeProc;
+ client_arguments.mapproc = fSuppressMap ? _tiffDummyMapProc : _tiffMapProc;
+ client_arguments.unmapproc = fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc;
+ client_arguments.errorhandler = arguments->errorhandler;
+ client_arguments.warnhandler = arguments->warnhandler;
+
+ tif = TIFFClientOpenExt(name, mode, thandle_from_int(ifd),
+ &client_arguments);
if (tif)
tif->tif_fd = ifd;
return (tif);
@@ -262,12 +295,36 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
TIFF*
TIFFOpen(const char* name, const char* mode)
{
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFOpenExt(name, mode, &arguments);
+}
+
+TIFF*
+TIFFOpenExt(const char* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
static const char module[] = "TIFFOpen";
thandle_t fd;
int m;
DWORD dwMode;
TIFF* tif;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+
m = _TIFFgetMode(mode, module);
switch(m) {
@@ -289,7 +346,7 @@ TIFFOpen(const char* name, const char* mode)
return ((TIFF *)0);
}
- tif = TIFFFdOpen(thandle_to_int(fd), name, mode);
+ tif = TIFFFdOpenExt(thandle_to_int(fd), name, mode, arguments);
if(!tif)
CloseHandle(fd);
return tif;
@@ -301,6 +358,19 @@ TIFFOpen(const char* name, const char* mode)
TIFF*
TIFFOpenW(const wchar_t* name, const char* mode)
{
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = NULL,
+ .errorhandler_user_data = NULL,
+ .warnhandler = NULL,
+ .warnhandler_user_data = NULL
+ };
+ return TIFFOpenWExt(name, mode, &arguments);
+}
+
+TIFF*
+TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenExtStruct* arguments)
+{
static const char module[] = "TIFFOpenW";
thandle_t fd;
int m;
@@ -309,6 +379,17 @@ TIFFOpenW(const wchar_t* name, const char* mode)
char *mbname;
TIFF *tif;
+ if (arguments == NULL)
+ {
+ TIFFErrorExt(0, module, "arguments should NOT be NULL");
+ return NULL;
+ }
+ if (arguments->version < 1)
+ {
+ TIFFErrorExt(0, module, "arguments->version should be >= 1");
+ return NULL;
+ }
+
m = _TIFFgetMode(mode, module);
switch(m) {
@@ -344,8 +425,9 @@ TIFFOpenW(const wchar_t* name, const char* mode)
NULL, NULL);
}
- tif = TIFFFdOpen(thandle_to_int(fd),
- (mbname != NULL) ? mbname : "<unknown>", mode);
+ tif = TIFFFdOpenExt(thandle_to_int(fd),
+ (mbname != NULL) ? mbname : "<unknown>", mode,
+ arguments);
if(!tif)
CloseHandle(fd);
diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h
index 0d6e4af2..36abdc4d 100644
--- a/libtiff/tiffio.h
+++ b/libtiff/tiffio.h
@@ -274,7 +274,7 @@ extern "C" {
#endif
typedef void (*TIFFErrorHandler)(const char*, const char*, va_list);
typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list);
-typedef int (*TIFFErrorHandlerExtR)(thandle_t, const char*, const char*, va_list);
+typedef int (*TIFFErrorHandlerExtR)(TIFF*, void* user_data, const char*, const char*, va_list);
typedef tmsize_t (*TIFFReadWriteProc)(thandle_t, void*, tmsize_t);
typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int);
typedef int (*TIFFCloseProc)(thandle_t);
@@ -460,28 +460,58 @@ extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt);
extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler);
extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt);
-extern void TIFFSetErrorHandlerExtR(TIFF*, TIFFErrorHandlerExtR);
-extern void TIFFSetWarningHandlerExtR(TIFF*, TIFFErrorHandlerExtR);
+extern void TIFFSetErrorHandlerExtR(TIFF*, TIFFErrorHandlerExtR, void* errorhandler_user_data);
+extern void TIFFSetWarningHandlerExtR(TIFF*, TIFFErrorHandlerExtR, void* warnhandler_user_data);
+extern void TIFFWarningExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
+extern void TIFFErrorExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
+
+typedef struct TIFFOpenExtStruct
+{
+ int version; /* should be set to 1 for now. */
+
+ TIFFErrorHandlerExtR errorhandler; /* may be NULL */
+ void* errorhandler_user_data; /* may be NULL */
+ TIFFErrorHandlerExtR warnhandler; /* may be NULL */
+ void* warnhandler_user_data; /* may be NULL */
+ /* If new fields are added, they should be handled by nVersion == 2 */
+} TIFFOpenExtStruct;
extern TIFF* TIFFOpen(const char*, const char*);
+extern TIFF* TIFFOpenExt(const char*, const char*, TIFFOpenExtStruct* arguments);
# ifdef __WIN32__
extern TIFF* TIFFOpenW(const wchar_t*, const char*);
+extern TIFF* TIFFOpenWExt(const wchar_t*, const char*, TIFFOpenExtStruct* arguments);
# endif /* __WIN32__ */
extern TIFF* TIFFFdOpen(int, const char*, const char*);
+extern TIFF* TIFFFdOpenExt(int, const char*, const char*, TIFFOpenExtStruct* arguments);
extern TIFF* TIFFClientOpen(const char*, const char*,
thandle_t,
TIFFReadWriteProc, TIFFReadWriteProc,
TIFFSeekProc, TIFFCloseProc,
TIFFSizeProc,
TIFFMapFileProc, TIFFUnmapFileProc);
-extern TIFF* TIFFClientOpenEx(const char*, const char*,
- thandle_t,
- TIFFReadWriteProc, TIFFReadWriteProc,
- TIFFSeekProc, TIFFCloseProc,
- TIFFSizeProc,
- TIFFMapFileProc, TIFFUnmapFileProc,
- TIFFErrorHandlerExtR, TIFFErrorHandlerExtR);
+typedef struct TIFFClientOpenExtStruct
+{
+ int version; /* should be set to 1 for now. */
+
+ TIFFReadWriteProc readproc; /* must *NOT* be NULL */
+ TIFFReadWriteProc writeproc; /* must *NOT* be NULL */
+ TIFFSeekProc seekproc; /* must *NOT* be NULL */
+ TIFFCloseProc closeproc; /* must *NOT* be NULL */
+ TIFFSizeProc sizeproc; /* must *NOT* be NULL */
+ TIFFMapFileProc mapproc; /* may be NULL */
+ TIFFUnmapFileProc unmapproc; /* may be NULL */
+ TIFFErrorHandlerExtR errorhandler; /* may be NULL */
+ void* errorhandler_user_data; /* may be NULL */
+ TIFFErrorHandlerExtR warnhandler; /* may be NULL */
+ void* warnhandler_user_data; /* may be NULL */
+ /* If new fields are added, they should be handled by nVersion == 2 */
+} TIFFClientOpenExtStruct;
+
+extern TIFF* TIFFClientOpenExt(const char*, const char*,
+ thandle_t,
+ TIFFClientOpenExtStruct* arguments);
extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc);
extern uint32_t TIFFComputeTile(TIFF* tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s);
extern int TIFFCheckTile(TIFF* tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s);
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index 1cca4f54..7fbeef4b 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -199,7 +199,9 @@ struct tiff {
size_t tif_nfieldscompat;
/* Error handler support */
TIFFErrorHandlerExtR tif_errorhandler;
+ void* tif_errorhandler_user_data;
TIFFErrorHandlerExtR tif_warnhandler;
+ void* tif_warnhandler_user_data;
};
#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
@@ -321,9 +323,6 @@ typedef size_t TIFFIOSize_t;
#if defined(__cplusplus)
extern "C" {
#endif
-extern void TIFFWarningExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
-extern void TIFFErrorExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
-
extern int _TIFFgetMode(const char* mode, const char* module);
extern int _TIFFNoRowEncode(TIFF* tif, uint8_t* pp, tmsize_t cc, uint16_t s);
extern int _TIFFNoStripEncode(TIFF* tif, uint8_t* pp, tmsize_t cc, uint16_t s);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3554b214..d7c18584 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -175,6 +175,11 @@ target_sources(testtypes PRIVATE testtypes.c)
target_link_libraries(testtypes PRIVATE tiff tiff_port)
list(APPEND simple_tests testtypes)
+add_executable(test_error_handlers ../placeholder.h)
+target_sources(test_error_handlers PRIVATE test_error_handlers.c)
+target_link_libraries(test_error_handlers PRIVATE tiff tiff_port)
+list(APPEND simple_tests test_error_handlers)
+
if(WEBP_SUPPORT AND EMSCRIPTEN)
# Emscripten is pretty finnicky about linker flags.
# It needs --shared-memory if and only if atomics or bulk-memory is used.
diff --git a/test/Makefile.am b/test/Makefile.am
index 09a83065..bcb69a4f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -75,7 +75,7 @@ endif
if TIFF_TESTS
check_PROGRAMS = \
ascii_tag long_tag short_tag strip_rw rewrite custom_dir custom_dir_EXIF_231 \
- defer_strile_loading defer_strile_writing test_directory \
+ defer_strile_loading defer_strile_writing test_directory test_error_handlers \
testtypes test_signed_tags $(JPEG_DEPENDENT_CHECK_PROG) $(STATIC_CHECK_PROGS)
endif
@@ -246,6 +246,8 @@ defer_strile_writing_SOURCES = defer_strile_writing.c
defer_strile_writing_LDADD = $(LIBTIFF)
test_directory_SOURCES = test_directory.c
test_directory_LDADD = $(LIBTIFF)
+test_error_handlers_SOURCES = test_error_handlers.c
+test_error_handlers_LDADD = $(LIBTIFF)
AM_CPPFLAGS = -I$(top_srcdir)/libtiff
diff --git a/test/test_error_handlers.c b/test/test_error_handlers.c
new file mode 100644
index 00000000..56faa29e
--- /dev/null
+++ b/test/test_error_handlers.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2022, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Test error handlers
+ */
+
+#include "tif_config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "tiffio.h"
+
+#define ERROR_STRING_SIZE 1024
+
+typedef struct MyErrorHandlerUserDataStruct
+{
+ char* buffer;
+ size_t buffer_size;
+ TIFF* tif_got_from_callback;
+ char module[64];
+} MyErrorHandlerUserDataStruct;
+
+static int myErrorHandler(TIFF* tiff, void* user_data, const char* module, const char* fmt, va_list ap)
+{
+ MyErrorHandlerUserDataStruct* errorhandler_user_data = (MyErrorHandlerUserDataStruct*)user_data;
+ vsnprintf(errorhandler_user_data->buffer,
+ errorhandler_user_data->buffer_size,
+ fmt,
+ ap);
+ errorhandler_user_data->tif_got_from_callback = tiff;
+ snprintf(errorhandler_user_data->module, sizeof(errorhandler_user_data->module), "%s", module);
+ return 1;
+}
+
+int test_open_ext(int handlers_set_in_open)
+{
+ int ret = 0;
+ char error_buffer[ERROR_STRING_SIZE] = {0};
+ char warn_buffer[ERROR_STRING_SIZE] = {0};
+ MyErrorHandlerUserDataStruct errorhandler_user_data =
+ {
+ .buffer = error_buffer,
+ .buffer_size = ERROR_STRING_SIZE
+ };
+ MyErrorHandlerUserDataStruct warnhandler_user_data =
+ {
+ .buffer = warn_buffer,
+ .buffer_size = ERROR_STRING_SIZE
+ };
+ TIFF* tif;
+ if( handlers_set_in_open )
+ {
+ TIFFOpenExtStruct arguments = {
+ .version = 1,
+ .errorhandler = myErrorHandler,
+ .errorhandler_user_data = &errorhandler_user_data,
+ .warnhandler = myErrorHandler,
+ .warnhandler_user_data = &warnhandler_user_data
+ };
+ tif = TIFFOpenExt("test_error_handler.tif", "w", &arguments);
+ }
+ else
+ {
+ tif = TIFFOpen("test_error_handler.tif", "w");
+ TIFFSetErrorHandlerExtR(tif, myErrorHandler, &errorhandler_user_data);
+ TIFFSetWarningHandlerExtR(tif, myErrorHandler, &warnhandler_user_data);
+ }
+ if( tif == NULL )
+ {
+ fprintf(stderr, "Cannot create test_error_handler.tif");
+ exit(1);
+ }
+
+ // Simulate an error emitted by libtiff
+ TIFFErrorExtR(tif, "my_error_module", "%s", "some error message");
+ if( strcmp(error_buffer, "some error message") != 0 )
+ {
+ fprintf(stderr, "Did not get expected error message\n");
+ ret = 1;
+ }
+ if( strcmp(errorhandler_user_data.module, "my_error_module") != 0 )
+ {
+ fprintf(stderr, "Did not get expected error module\n");
+ ret = 1;
+ }
+ if( errorhandler_user_data.tif_got_from_callback != tif)
+ {
+ fprintf(stderr, "errorhandler_user_data.tif_got_from_callback != tif\n");
+ ret = 1;
+ }
+
+ // Simulate a warning emitted by libtiff
+ TIFFWarningExtR(tif, "my_warning_module", "%s", "some warning message");
+ if( strcmp(warn_buffer, "some warning message") != 0 )
+ {
+ fprintf(stderr, "Did not get expected warning message\n");
+ ret = 1;
+ }
+ if( strcmp(warnhandler_user_data.module, "my_warning_module") != 0 )
+ {
+ fprintf(stderr, "Did not get expected warning module\n");
+ ret = 1;
+ }
+ if( warnhandler_user_data.tif_got_from_callback != tif)
+ {
+ fprintf(stderr, "warnhandler_user_data.tif_got_from_callback != tif\n");
+ ret = 1;
+ }
+
+ TIFFClose(tif);
+ unlink("test_error_handler.tif");
+ return ret;
+}
+
+int main()
+{
+ int ret = 0;
+ ret += test_open_ext(1);
+ ret += test_open_ext(0);
+ return ret;
+}