diff options
author | Even Rouault <even.rouault@spatialys.com> | 2022-11-21 23:59:12 +0000 |
---|---|---|
committer | Even Rouault <even.rouault@spatialys.com> | 2022-11-21 23:59:12 +0000 |
commit | d95b5b7628da6e0f446f7289059e1248de12dec9 (patch) | |
tree | 61529d7a0de59fa2f65899a56b7df70e0b335736 | |
parent | e7e567536baddd491e124f6fc5e11e80e740934e (diff) | |
parent | ec18caeb67e751fb50b5777c9b4d7c9cf2a71683 (diff) | |
download | libtiff-git-d95b5b7628da6e0f446f7289059e1248de12dec9.tar.gz |
Merge branch 'TIFFOpenEx' into 'master'
Add TIFFOpenExt(), TIFFOpenWExt() and TIFFFdOpenExt() with re-entrant error handlers
See merge request libtiff/libtiff!413
-rw-r--r-- | doc/functions/TIFFError.rst | 8 | ||||
-rw-r--r-- | doc/functions/TIFFOpen.rst | 39 | ||||
-rw-r--r-- | doc/functions/TIFFWarning.rst | 3 | ||||
-rw-r--r-- | libtiff/libtiff.def | 11 | ||||
-rw-r--r-- | libtiff/libtiff.map | 11 | ||||
-rw-r--r-- | libtiff/tif_error.c | 24 | ||||
-rw-r--r-- | libtiff/tif_open.c | 58 | ||||
-rw-r--r-- | libtiff/tif_unix.c | 58 | ||||
-rw-r--r-- | libtiff/tif_warning.c | 6 | ||||
-rw-r--r-- | libtiff/tif_win32.c | 50 | ||||
-rw-r--r-- | libtiff/tiffio.h | 30 | ||||
-rw-r--r-- | libtiff/tiffiop.h | 16 | ||||
-rw-r--r-- | test/CMakeLists.txt | 5 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/test_error_handlers.c | 140 |
15 files changed, 393 insertions, 70 deletions
diff --git a/doc/functions/TIFFError.rst b/doc/functions/TIFFError.rst index f03eef8c..797c1c0e 100644 --- a/doc/functions/TIFFError.rst +++ b/doc/functions/TIFFError.rst @@ -43,7 +43,13 @@ as *fd*, which represents the TIFF file handle (file descriptor). .. TODO: Check description, how to setup a TIFFErrorExt handler and its file handle. -With :c:func:`TIFFSetErrorHandlerExt` an extra error handler can be setup. +With :c:func:`TIFFSetErrorHandlerExt` an extra error handler can be setup +in order to write to a file. The file handle needs to be stored in +``tif->tif_clientdata`` if the ``libtiff`` internal errors shall also +be written to that file. + +Note that, starting with libtiff 4.5, a per-TIFF handler may also be installed +with :c:func:`TIFFOpenExt` or :c:func:`TIFFClientOpenExt` Note ---- diff --git a/doc/functions/TIFFOpen.rst b/doc/functions/TIFFOpen.rst index 29c7cfc6..7566ef62 100644 --- a/doc/functions/TIFFOpen.rst +++ b/doc/functions/TIFFOpen.rst @@ -35,6 +35,22 @@ Synopsis .. c:function:: thandle_t TIFFSetClientdata(TIFF* tif, thandle_t newvalue) +.. c:function:: TIFFOpenOptions* TIFFOpenOptionsAlloc(void) + +.. c:function:: void TIFFOpenOptionsFree(TIFFOpenOptions*); + +.. c:function:: void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data) + +.. c:function:: void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data) + +.. c:function:: TIFF* TIFFOpenExt(const char* filename, const char* mode, TIFFOpenOptions* opts) + +.. c:function:: TIFF* TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts) + +.. c:function:: TIFF* TIFFFdOpenExt(const int fd, const char* filename, const char*mode, TIFFOpenOptions* opts) + +.. c:function:: TIFF* TIFFClientOpenExt(const char* filename, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc, TIFFOpenOptions* opts) + Description ----------- @@ -86,6 +102,24 @@ first :c:func:`TIFFCleanup` should be called to free the internal TIFF structure without closing the file handle and afterwards the file should be closed using its file descriptor *fd*. +:c:func:`TIFFOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFOpen`, but options, +such as re-entrant error and warning handlers may be passed. The opts argument +may be NULL. Note that in the early stages of the execution of the function, +the TIFF* argument passed to the re-entrant error handler (specified in opts) +may be NULL. + +:c:func:`TIFFOpenWExt` (added in libtiff 4.5) is like :c:func:`TIFFOpenW`, but options, +such as re-entrant error and warning handlers may be passed. The opts argument +may be NULL. Note that in the early stages of the execution of the function, +the TIFF* argument passed to the re-entrant error handler (specified in opts) +may be NULL. + +:c:func:`TIFFFdOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFFdOpen`, but options, +such as re-entrant error and warning handlers may be passed. The opts argument +may be NULL. Note that in the early stages of the execution of the function, +the TIFF* argument passed to the re-entrant error handler (specified in opts) +may be NULL. + :c:func:`TIFFSetFileName` sets the file name in the tif-structure and returns the old file name. @@ -123,6 +157,11 @@ The clientdata is used as open file's I/O descriptor within ``libtiff``. When updating the file's clientdata with :c:func:`TIFFSetClientdata`, the *fd* value is **not** updated. +:c:func:`TIFFClientOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFClientOpen`, but options, +such as re-entrant error and warning handlers may be passed. The opts argument +may be NULL. Note that in the early stages of the execution of the function, +the TIFF* argument passed to the re-entrant error handler (specified in opts) +may be NULL. Options ------- diff --git a/doc/functions/TIFFWarning.rst b/doc/functions/TIFFWarning.rst index 38bfbf1c..2006696c 100644 --- a/doc/functions/TIFFWarning.rst +++ b/doc/functions/TIFFWarning.rst @@ -49,6 +49,9 @@ as *fd*, which represents the TIFF file handle (file descriptor). With :c:func:`TIFFSetWarningHandlerExt` an extra warning handler can be setup up. +Note that, starting with libtiff 4.5, a per-TIFF handler may also be installed +with :c:func:`TIFFOpenExt` or :c:func:`TIFFClientOpenExt` + Note ---- diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def index ee5486a6..975ad1fd 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,13 @@ EXPORTS TIFFAccessTagMethods TIFFNumberOfStrips TIFFNumberOfTiles TIFFOpen + TIFFOpenExt TIFFOpenW + TIFFOpenWExt + TIFFOpenOptionsAlloc + TIFFOpenOptionsFree + TIFFOpenOptionsSetErrorHandlerExtR + TIFFOpenOptionsSetWarningHandlerExtR TIFFPrintDirectory TIFFRGBAImageBegin TIFFRGBAImageEnd @@ -156,6 +164,7 @@ EXPORTS TIFFAccessTagMethods TIFFVTileSize64 TIFFWarning TIFFWarningExt + TIFFWarningExtR TIFFWriteBufferSetup TIFFWriteCheck TIFFWriteCustomDirectory diff --git a/libtiff/libtiff.map b/libtiff/libtiff.map index 4c66ed41..c811a751 100644 --- a/libtiff/libtiff.map +++ b/libtiff/libtiff.map @@ -202,5 +202,14 @@ LIBTIFF_4.4 { LIBTIFF_4.5 { _TIFFClampDoubleToUInt32; - TIFFClientOpenEx; + TIFFClientOpenExt; + TIFFFdOpenExt; + TIFFOpenExt; + TIFFOpenWExt; + TIFFErrorExtR; + TIFFWarningExtR; + TIFFOpenOptionsAlloc; + TIFFOpenOptionsFree; + TIFFOpenOptionsSetErrorHandlerExtR; + TIFFOpenOptionsSetWarningHandlerExtR; } LIBTIFF_4.4; diff --git a/libtiff/tif_error.c b/libtiff/tif_error.c index 2bd74d52..4065d60a 100644 --- a/libtiff/tif_error.c +++ b/libtiff/tif_error.c @@ -77,16 +77,34 @@ TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...) } } -void TIFFSetErrorHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) { - if (tif) tif->tif_errorhandler = handler; +void _TIFFErrorEarly(TIFFOpenOptions* opts, thandle_t clientdata, const char* module, const char* fmt, ...) +{ + va_list ap; + if (opts && opts->errorhandler) { + va_start(ap, fmt); + int stop = opts->errorhandler(NULL, opts->errorhandler_user_data, module, fmt, ap); + va_end(ap); + if (stop) return; + } + if (_TIFFerrorHandler) { + va_start(ap, fmt); + (*_TIFFerrorHandler)(module, fmt, ap); + va_end(ap); + } + if (_TIFFerrorHandlerExt) { + va_start(ap, fmt); + (*_TIFFerrorHandlerExt)(clientdata, module, fmt, ap); + va_end(ap); + } } + 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..23e206d7 100644 --- a/libtiff/tif_open.c +++ b/libtiff/tif_open.c @@ -44,7 +44,7 @@ _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size) } int -_TIFFgetMode(const char* mode, const char* module) +_TIFFgetMode(TIFFOpenOptions* opts, thandle_t clientdata, const char* mode, const char* module) { int m = -1; @@ -61,12 +61,35 @@ _TIFFgetMode(const char* mode, const char* module) m |= O_TRUNC; break; default: - TIFFErrorExt(0, module, "\"%s\": Bad mode", mode); + _TIFFErrorEarly(opts, clientdata, module, "\"%s\": Bad mode", mode); break; } return (m); } +TIFFOpenOptions* TIFFOpenOptionsAlloc() +{ + TIFFOpenOptions* opts = (TIFFOpenOptions*)_TIFFcalloc(1, sizeof(TIFFOpenOptions)); + return opts; +} + +void TIFFOpenOptionsFree(TIFFOpenOptions* opts) +{ + _TIFFfree(opts); +} + +void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data) +{ + opts->errorhandler = handler; + opts->errorhandler_user_data = errorhandler_user_data; +} + +void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data) +{ + opts->warnhandler = handler; + opts->warnhandler_user_data = warnhandler_user_data; +} + TIFF* TIFFClientOpen( const char* name, const char* mode, @@ -79,12 +102,19 @@ TIFFClientOpen( TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { - return TIFFClientOpenEx(name, mode, clientdata, readproc, writeproc, seekproc, closeproc, - sizeproc, mapproc, unmapproc, NULL, NULL); + return TIFFClientOpenExt(name, mode, clientdata, + readproc, + writeproc, + seekproc, + closeproc, + sizeproc, + mapproc, + unmapproc, + NULL); } TIFF* -TIFFClientOpenEx( +TIFFClientOpenExt( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, @@ -94,10 +124,9 @@ TIFFClientOpenEx( TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc, - TIFFErrorHandlerExtR errorhandler, - TIFFErrorHandlerExtR warnhandler) + TIFFOpenOptions* opts) { - static const char module[] = "TIFFClientOpenEx"; + static const char module[] = "TIFFClientOpenExt"; TIFF *tif; int m; const char* cp; @@ -128,12 +157,12 @@ TIFFClientOpenEx( #endif } - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(opts, clientdata, mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); if (tif == NULL) { - TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); + _TIFFErrorEarly(opts, clientdata, module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); @@ -152,8 +181,13 @@ 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; + if( opts ) + { + tif->tif_errorhandler = opts->errorhandler; + tif->tif_errorhandler_user_data = opts->errorhandler_user_data; + tif->tif_warnhandler = opts->warnhandler; + tif->tif_warnhandler_user_data = opts->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..89ae0c17 100644 --- a/libtiff/tif_unix.c +++ b/libtiff/tif_unix.c @@ -202,18 +202,29 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size) TIFF* TIFFFdOpen(int fd, const char* name, const char* mode) { + return TIFFFdOpenExt(fd, name, mode, NULL); +} + +TIFF* +TIFFFdOpenExt(int fd, const char* name, const char* mode, TIFFOpenOptions* opts) +{ TIFF* tif; - fd_as_handle_union_t fdh; - fdh.fd = fd; - tif = TIFFClientOpen(name, mode, - fdh.h, - _tiffReadProc, _tiffWriteProc, - _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, - _tiffMapProc, _tiffUnmapProc); - if (tif) - tif->tif_fd = fd; - return (tif); + fd_as_handle_union_t fdh; + fdh.fd = fd; + tif = TIFFClientOpenExt(name, mode, + fdh.h, + _tiffReadProc, + _tiffWriteProc, + _tiffSeekProc, + _tiffCloseProc, + _tiffSizeProc, + _tiffMapProc, + _tiffUnmapProc, + opts); + if (tif) + tif->tif_fd = fd; + return (tif); } /* @@ -222,11 +233,17 @@ TIFFFdOpen(int fd, const char* name, const char* mode) TIFF* TIFFOpen(const char* name, const char* mode) { + return TIFFOpenExt(name, mode, NULL); +} + +TIFF* +TIFFOpenExt(const char* name, const char* mode, TIFFOpenOptions* opts) +{ static const char module[] = "TIFFOpen"; int m, fd; TIFF* tif; - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(opts, NULL, mode, module); if (m == -1) return ((TIFF*)0); @@ -238,14 +255,14 @@ TIFFOpen(const char* name, const char* mode) fd = open(name, m, 0666); if (fd < 0) { if (errno > 0 && strerror(errno) != NULL ) { - TIFFErrorExt(0, module, "%s: %s", name, strerror(errno) ); + _TIFFErrorEarly(opts, NULL, module, "%s: %s", name, strerror(errno) ); } else { - TIFFErrorExt(0, module, "%s: Cannot open", name); + _TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name); } return ((TIFF *)0); } - tif = TIFFFdOpen((int)fd, name, mode); + tif = TIFFFdOpenExt((int)fd, name, mode, opts); if(!tif) close(fd); return tif; @@ -259,6 +276,11 @@ TIFFOpen(const char* name, const char* mode) TIFF* TIFFOpenW(const wchar_t* name, const char* mode) { + return TIFFOpenWEx(name, mode, NULL); +} +TIFF* +TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts) +{ static const char module[] = "TIFFOpenW"; int m, fd; int mbsize; @@ -276,7 +298,7 @@ TIFFOpenW(const wchar_t* name, const char* mode) fd = _wopen(name, m, 0666); if (fd < 0) { - TIFFErrorExt(0, module, "%ls: Cannot open", name); + _TIFFErrorEarly(opts, NULL, module, "%ls: Cannot open", name); return ((TIFF *)0); } @@ -285,7 +307,7 @@ TIFFOpenW(const wchar_t* name, const char* mode) if (mbsize > 0) { mbname = _TIFFmalloc(mbsize); if (!mbname) { - TIFFErrorExt(0, module, + _TIFFErrorEarly(opts, NULL, module, "Can't allocate space for filename conversion buffer"); return ((TIFF*)0); } @@ -294,8 +316,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, opts); _TIFFfree(mbname); diff --git a/libtiff/tif_warning.c b/libtiff/tif_warning.c index aa26faca..29e26bec 100644 --- a/libtiff/tif_warning.c +++ b/libtiff/tif_warning.c @@ -77,16 +77,12 @@ TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...) } } -void TIFFSetWarningHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) { - if (tif) tif->tif_warnhandler = handler; -} - 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..955957b7 100644 --- a/libtiff/tif_win32.c +++ b/libtiff/tif_win32.c @@ -232,9 +232,16 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size) TIFF* TIFFFdOpen(int ifd, const char* name, const char* mode) { + return TIFFFdOpenExt(ifd, name, mode, NULL); +} + +TIFF* +TIFFFdOpenExt(int ifd, const char* name, const char* mode, TIFFOpenOptions* opts) +{ TIFF* tif; int fSuppressMap; int m; + fSuppressMap=0; for (m=0; mode[m]!=0; m++) { @@ -244,11 +251,16 @@ 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); + + tif = TIFFClientOpenExt(name, mode, thandle_from_int(ifd), + _tiffReadProc, + _tiffWriteProc, + _tiffSeekProc, + _tiffCloseProc, + _tiffSizeProc, + fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, + fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc, + opts); if (tif) tif->tif_fd = ifd; return (tif); @@ -262,13 +274,19 @@ TIFFFdOpen(int ifd, const char* name, const char* mode) TIFF* TIFFOpen(const char* name, const char* mode) { + return TIFFOpenExt(name, mode, NULL); +} + +TIFF* +TIFFOpenExt(const char* name, const char* mode, TIFFOpenOptions* opts) +{ static const char module[] = "TIFFOpen"; thandle_t fd; int m; DWORD dwMode; TIFF* tif; - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(opts, NULL, mode, module); switch(m) { case O_RDONLY: dwMode = OPEN_EXISTING; break; @@ -285,11 +303,11 @@ TIFFOpen(const char* name, const char* mode) (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, NULL); if (fd == INVALID_HANDLE_VALUE) { - TIFFErrorExt(0, module, "%s: Cannot open", name); + _TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name); return ((TIFF *)0); } - tif = TIFFFdOpen(thandle_to_int(fd), name, mode); + tif = TIFFFdOpenExt(thandle_to_int(fd), name, mode, opts); if(!tif) CloseHandle(fd); return tif; @@ -301,6 +319,12 @@ TIFFOpen(const char* name, const char* mode) TIFF* TIFFOpenW(const wchar_t* name, const char* mode) { + return TIFFOpenWExt(name, mode, NULL); +} + +TIFF* +TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts) +{ static const char module[] = "TIFFOpenW"; thandle_t fd; int m; @@ -309,7 +333,7 @@ TIFFOpenW(const wchar_t* name, const char* mode) char *mbname; TIFF *tif; - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(opts, NULL, mode, module); switch(m) { case O_RDONLY: dwMode = OPEN_EXISTING; break; @@ -326,7 +350,7 @@ TIFFOpenW(const wchar_t* name, const char* mode) (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, NULL); if (fd == INVALID_HANDLE_VALUE) { - TIFFErrorExt(0, module, "%S: Cannot open", name); + _TIFFErrorEarly(opts, NULL, module, "%S: Cannot open", name); return ((TIFF *)0); } @@ -335,7 +359,7 @@ TIFFOpenW(const wchar_t* name, const char* mode) if (mbsize > 0) { mbname = (char *)_TIFFmalloc(mbsize); if (!mbname) { - TIFFErrorExt(0, module, + _TIFFErrorEarly(opts, NULL, module, "Can't allocate space for filename conversion buffer"); return ((TIFF*)0); } @@ -344,8 +368,8 @@ 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, opts); if(!tif) CloseHandle(fd); diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h index 0d6e4af2..7d12a88c 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,36 @@ extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt); extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler); extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt); -extern void TIFFSetErrorHandlerExtR(TIFF*, TIFFErrorHandlerExtR); -extern void TIFFSetWarningHandlerExtR(TIFF*, TIFFErrorHandlerExtR); +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 TIFFOpenOptions TIFFOpenOptions; +extern TIFFOpenOptions* TIFFOpenOptionsAlloc(void); +extern void TIFFOpenOptionsFree(TIFFOpenOptions*); +extern void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data); +extern void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data); extern TIFF* TIFFOpen(const char*, const char*); +extern TIFF* TIFFOpenExt(const char*, const char*, TIFFOpenOptions* opts); # ifdef __WIN32__ extern TIFF* TIFFOpenW(const wchar_t*, const char*); +extern TIFF* TIFFOpenWExt(const wchar_t*, const char*, TIFFOpenOptions* opts); # endif /* __WIN32__ */ extern TIFF* TIFFFdOpen(int, const char*, const char*); +extern TIFF* TIFFFdOpenExt(int, const char*, const char*, TIFFOpenOptions* opts); 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); - +extern TIFF* TIFFClientOpenExt(const char*, const char*, + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc, + TIFFOpenOptions* opts); 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..d52fc45f 100644 --- a/libtiff/tiffiop.h +++ b/libtiff/tiffiop.h @@ -199,7 +199,17 @@ 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; +}; + +struct TIFFOpenOptions +{ + TIFFErrorHandlerExtR errorhandler; /* may be NULL */ + void* errorhandler_user_data; /* may be NULL */ + TIFFErrorHandlerExtR warnhandler; /* may be NULL */ + void* warnhandler_user_data; /* may be NULL */ }; #define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ @@ -321,10 +331,7 @@ 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 _TIFFgetMode(TIFFOpenOptions* opts, thandle_t clientdata, 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); extern int _TIFFNoTileEncode(TIFF*, uint8_t* pp, tmsize_t cc, uint16_t s); @@ -360,6 +367,7 @@ extern TIFFErrorHandler _TIFFwarningHandler; extern TIFFErrorHandler _TIFFerrorHandler; extern TIFFErrorHandlerExt _TIFFwarningHandlerExt; extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; +void _TIFFErrorEarly(TIFFOpenOptions* opts, thandle_t clientdata, const char* module, const char* fmt, ...) TIFF_ATTRIBUTE((__format__ (__printf__,4,5))); extern uint32_t _TIFFMultiply32(TIFF*, uint32_t, uint32_t, const char*); extern uint64_t _TIFFMultiply64(TIFF*, uint64_t, uint64_t, const char*); 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..f0e8e3ea --- /dev/null +++ b/test/test_error_handlers.c @@ -0,0 +1,140 @@ +/* + * 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 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 + }; + + TIFFOpenOptions* opts = TIFFOpenOptionsAlloc(); + assert(opts); + TIFFOpenOptionsSetErrorHandlerExtR(opts, myErrorHandler, &errorhandler_user_data); + TIFFOpenOptionsSetWarningHandlerExtR(opts, myErrorHandler, &warnhandler_user_data); + TIFF* tif = TIFFOpenExt("test_error_handler.tif", "w", opts); + TIFFOpenOptionsFree(opts); + + 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); + return ret; +} |