diff options
author | Even Rouault <even.rouault@spatialys.com> | 2022-11-10 17:27:08 +0100 |
---|---|---|
committer | Even Rouault <even.rouault@spatialys.com> | 2022-11-21 23:21:13 +0100 |
commit | 91e95ee9ae9cc91b5e657cb078827c361da9b1ae (patch) | |
tree | 91a4bf83b281ea92793504a6fdb4d0e532b032dc | |
parent | e7e567536baddd491e124f6fc5e11e80e740934e (diff) | |
download | libtiff-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.def | 9 | ||||
-rw-r--r-- | libtiff/libtiff.map | 9 | ||||
-rw-r--r-- | libtiff/tif_error.c | 9 | ||||
-rw-r--r-- | libtiff/tif_open.c | 55 | ||||
-rw-r--r-- | libtiff/tif_unix.c | 99 | ||||
-rw-r--r-- | libtiff/tif_warning.c | 9 | ||||
-rw-r--r-- | libtiff/tif_win32.c | 98 | ||||
-rw-r--r-- | libtiff/tiffio.h | 50 | ||||
-rw-r--r-- | libtiff/tiffiop.h | 5 | ||||
-rw-r--r-- | test/CMakeLists.txt | 5 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/test_error_handlers.c | 151 |
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; +} |