From 5b9bca7b129d8fd87a6014ec92cf5bbbe46cdadc Mon Sep 17 00:00:00 2001 From: jkriege2 Date: Wed, 8 May 2024 12:47:08 +0200 Subject: [PATCH] fortify source against memory attacks (using ..._s-functions portably, or __builtin___..._chk-functions) --- .github/workflows/build_linux.yml | 3 +- src/CMakeLists.txt | 6 + src/tiff_definitions_internal.h | 16 +-- src/tinytiff_ctools_internal.c | 81 ++++++++++++ src/tinytiff_ctools_internal.h | 90 +++++++++++++ src/tinytiffreader.c | 18 ++- src/tinytiffreader.h | 5 +- src/tinytiffwriter.c | 119 ++++-------------- src/tinytiffwriter.h | 5 +- .../tinytiffwriter_test.cpp | 40 ++++-- 10 files changed, 252 insertions(+), 131 deletions(-) create mode 100644 src/tinytiff_ctools_internal.c create mode 100644 src/tinytiff_ctools_internal.h diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 3f21af1..f37d96f 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -37,7 +37,8 @@ jobs: ls -R - name: Build Debug run: | - cmake --build build --config Release --verbose + cmake -G "${{matrix.gen}}" -DBUILD_SHARED_LIBS=${{matrix.shared}} "-DTinyTIFF_BUILD_TESTS=OFF" -DCMAKE_CXX_COMPILER=${{matrix.cxxcompiler}} -DCMAKE_C_COMPILER=${{matrix.ccompiler}} -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_C_FLAGS_ALL_WARNINGS:STRING="-Wall" -B build_debug + cmake --build build_debug --config Debug --verbose - name: Test CMake-build against TinyTIFF run: | cd tests diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c7b2049..ff6eeaa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ check_symbol_exists(fread_s "stdio.h" HAVE_FREAD_S) check_symbol_exists(sprintf_s "stdio.h" HAVE_SPRINTF_S) check_symbol_exists(strcat_s "string.h" HAVE_STRCAT_S) check_symbol_exists(memcpy_s "string.h" HAVE_MEMCPY_S) +check_symbol_exists(memset_s "string.h" HAVE_MEMSET_S) check_symbol_exists(strnlen_s "string.h" HAVE_STRNLEN_S) @@ -88,6 +89,9 @@ endif() if (HAVE_MEMCPY_S) target_compile_definitions(${lib_name} PRIVATE HAVE_MEMCPY_S) endif() +if (HAVE_MEMSET_S) + target_compile_definitions(${lib_name} PRIVATE HAVE_MEMSET_S) +endif() if (HAVE_STRNLEN_S) target_compile_definitions(${lib_name} PRIVATE HAVE_STRNLEN_S) endif() @@ -108,6 +112,7 @@ set_property(SOURCE tinytiffreader.c tinytiffreader.h PROPERTY LANGUAGE "C") set_property(SOURCE tinytiffwriter.c tinytiffwriter.h PROPERTY LANGUAGE "C") set_property(SOURCE tiff_definitions_internal.h tinytiff_defs.h PROPERTY LANGUAGE "C") target_sources(${lib_name} PRIVATE + tinytiff_ctools_internal.c tinytiffreader.c tinytiffwriter.c ) @@ -116,6 +121,7 @@ target_sources(${lib_name} PRIVATE target_sources(${lib_name} PRIVATE FILE_SET privateHEADERS TYPE HEADERS FILES tiff_definitions_internal.h + tinytiff_ctools_internal.h ) target_sources(${lib_name} PUBLIC FILE_SET HEADERS TYPE HEADERS diff --git a/src/tiff_definitions_internal.h b/src/tiff_definitions_internal.h index 6e2cbe8..b276ef4 100644 --- a/src/tiff_definitions_internal.h +++ b/src/tiff_definitions_internal.h @@ -16,6 +16,10 @@ */ +#include +#include +#include + #ifndef TIFF_DEFINITIONS_INTERNAL_H #define TIFF_DEFINITIONS_INTERNAL_H @@ -94,16 +98,4 @@ -#ifdef HAVE_STRCPY_S -#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message); -#else -#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy(tiff->lastError, message); -#endif - -#ifdef HAVE_SPRINTF_S -#define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message, __VA_ARGS__); -#else -#define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf(tiff->lastError, message, __VA_ARGS__); -#endif - #endif // TIFF_DEFINITIONS_INTERNAL_H diff --git a/src/tinytiff_ctools_internal.c b/src/tinytiff_ctools_internal.c new file mode 100644 index 0000000..3b40e86 --- /dev/null +++ b/src/tinytiff_ctools_internal.c @@ -0,0 +1,81 @@ +/* + Copyright (c) 2008-2024 Jan W. Krieger (), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + +*/ +#include "tinytiff_ctools_internal.h" +#include +#include + +#ifdef __has_builtin + +# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin (__builtin___memcpy_chk) +# define tinytiff_builtin_memcpy_chk(dest, src, n) __builtin___memcpy_chk(dest, src, n, tinytiff_builtin_object_size0(dest)) +# endif + +# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin (__builtin___memset_chk) +# define tinytiff_builtin_memset_chk(dest, ch, n) __builtin___memset_chk(dest, ch, n, tinytiff_builtin_object_size0(dest)) +# endif + +#endif + +void TinyTIFF_memcpy_s(void *dest, unsigned long destsz, const void *src, unsigned long count) { + if (count<=0) return; +#ifdef HAVE_MEMCPY_S + memcpy_s(dest, destsz, src, count); +#else +# if defined(tinytiff_builtin_memcpy_chk) + tinytiff_builtin_memcpy_chk(dest, src, count); +# else + assert((dest!=NULL) && "TinyTIFF_memcpy_s: dest==NULL"); + assert((src!=NULL) && "TinyTIFF_memcpy_s: src==NULL"); + #if defined(TINYTIFF_HASOBJSIZE) + assert((tinytiff_builtin_object_size(dest,1)>=destsz) && "TinyTIFF_memcpy_s: dest too small (destsz incorrect)"); + assert((tinytiff_builtin_object_size(dest,1)>=count) && "TinyTIFF_memcpy_s: dest too small (count larger than available memory)"); + assert((tinytiff_builtin_object_size(src,1)>=count) && "TinyTIFF_memcpy_s: src too small"); + #endif + memcpy(dest, src, count); +# endif +#endif +} + +void TinyTIFF_memset_s(void *dest, unsigned long destsz, char ch, unsigned long count) +{ +#ifdef HAVE_MEMSET_S + memset_s(dest, destsz, ch, count); +#else +# if defined(tinytiff_builtin_memset_chk) + tinytiff_builtin_memset_chk(dest, ch, count); +# else + memset(dest, ch, count); +# endif +#endif + +} + +unsigned long TinyTIFF_strlen_s(const char *str, unsigned long strsz) +{ +#ifdef HAVE_STRLEN_S + return strlen_s(str, strsz); +#else + if (str==NULL) return 0; + #if defined(TINYTIFF_HASOBJSIZE) + assert((tinytiff_builtin_object_size1(str)>=strsz) && "TinyTIFF_strlen_s: str too small (strsz incorrect)"); + #endif + return strlen(str); +#endif + +} diff --git a/src/tinytiff_ctools_internal.h b/src/tinytiff_ctools_internal.h new file mode 100644 index 0000000..0e751f2 --- /dev/null +++ b/src/tinytiff_ctools_internal.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2008-2024 Jan W. Krieger (), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + +*/ + + +#ifndef TINYTIFF_CTOOLS_INTERNAL_H +#define TINYTIFF_CTOOLS_INTERNAL_H + +#if defined(__has_builtin) +# if __has_builtin(__builtin_object_size) +# define tinytiff_builtin_object_size(ptr) __builtin_object_size(ptr, 2) +# define tinytiff_builtin_object_size0(dest) __builtin_object_size (dest, 0) +# define tinytiff_builtin_object_size1(dest) __builtin_object_size (dest, 1) +# define TINYTIFF_HASOBJSIZE +# endif +#endif + +#ifdef HAVE_STRCPY_S +#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message); +#define TINYTIFF_STRCPY_S(dest, dsize, src) strcpy_s(dest, dsize, src); +#else +# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___strcpy_chk) +# define TINYTIFF_SET_LAST_ERROR(tiff, message) __builtin___strcpy_chk(tiff->lastError, message, tinytiff_builtin_object_size0(tiff->lastError)) +# define TINYTIFF_STRCPY_S(dest, dsize, src) __builtin___strcpy_chk(dest, src, tinytiff_builtin_object_size0(dest)) +# else +# define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy(tiff->lastError, message); +# define TINYTIFF_STRCPY_S(dest, dsize, src) strcpy(dest, src); +# endif +#endif + + +#ifdef HAVE_STRCAT_S +#define TINYTIFF_STRCAT_S(dest, dsize, src) strcat_s(dest, dsize, src); +#else +# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___strcat_chk) +# define TINYTIFF_STRCAT_S(dest, dsize, src) __builtin___strcat_chk(dest, src, tinytiff_builtin_object_size0(dest)) +# else +# define TINYTIFF_STRCAT_S(dest, dsize, src) strcat(dest, src); +# endif +#endif + + +#ifdef HAVE_SPRINTF_S +# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) sprintf_s(str, ssize, message, __VA_ARGS__); +# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message, __VA_ARGS__); +#else +# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___sprintf_chk) +# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) __builtin___sprintf_chk(tiff->lastError, 0, tinytiff_builtin_object_size0(tiff->lastError), message, __VA_ARGS__) +# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) __builtin___sprintf_chk(str, 0, tinytiff_builtin_object_size0(str), message, __VA_ARGS__) +# else +# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) sprintf(str, message, __VA_ARGS__); +# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf(tiff->lastError, message, __VA_ARGS__); +# endif +#endif + + +/** \brief hardened memcpy(), that calls memcpy_s() or __builtin___memcpy_chk() if available + * \internal + * \ingroup tinytiffreader_internal + */ +void TinyTIFF_memcpy_s( void * dest, unsigned long destsz, const void * src, unsigned long count ); + +/** \brief hardened memset(), that calls memset_s() or __builtin___memset_chk() if available + * \internal + * \ingroup tinytiffreader_internal + */ +void TinyTIFF_memset_s( void * dest, unsigned long destsz, char ch, unsigned long count ); + +/** \brief hardened strlen(), that calls strlen_s() or __builtin___strlen_chk() if available + * \internal + * \ingroup tinytiffreader_internal + */ +unsigned long TinyTIFF_strlen_s( const char * str, unsigned long strsz); + +#endif // TINYTIFF_CTOOLS_INTERNAL_H diff --git a/src/tinytiffreader.c b/src/tinytiffreader.c index b0dd2a3..5ee4627 100644 --- a/src/tinytiffreader.c +++ b/src/tinytiffreader.c @@ -18,12 +18,16 @@ */ #include "tinytiffreader.h" #include "tiff_definitions_internal.h" +#include "tinytiff_ctools_internal.h" #include "tinytiff_version.h" //#define DEBUG_IFDTIMING #ifdef DEBUG_IFDTIMING #include "highrestimer.h" #endif +#include +#include +#include #include #include @@ -189,14 +193,6 @@ unsigned long TinyTIFFReader_doRangesOverlap(unsigned long xstart, unsigned long return TINYTIFF_FALSE; } -int TinyTIFFReader_memcpy_s( void * dest, unsigned long destsz, const void * src, unsigned long count ) { -#ifdef HAVE_MEMCPY_S - return memcpy_s(dest, destsz, src, count); -#else - memcpy(dest, src, count); - return 0; -#endif -} void TinyTIFFReader_fopen(TinyTIFFReaderFile* tiff, const char* filename) { #ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO @@ -618,7 +614,7 @@ static void TinyTIFFReader_readNextFrame(TinyTIFFReaderFile* tiff) { tiff->currentFrame.stripcount=ifd.count; tiff->currentFrame.stripoffsets=(uint32_t*)calloc(ifd.count, sizeof(uint32_t)); if (tiff->currentFrame.stripoffsets) { - TinyTIFFReader_memcpy_s(tiff->currentFrame.stripoffsets, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t)); + TinyTIFF_memcpy_s(tiff->currentFrame.stripoffsets, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t)); } else { tiff->wasError=TINYTIFF_TRUE; TINYTIFF_SET_LAST_ERROR(tiff, "unable to allocate memory\0"); @@ -652,7 +648,7 @@ static void TinyTIFFReader_readNextFrame(TinyTIFFReaderFile* tiff) { if (ifd.count>0 && ifd.pvalue) { tiff->currentFrame.stripcount=ifd.count; tiff->currentFrame.stripbytecounts=(uint32_t*)calloc(ifd.count, sizeof(uint32_t)); - TinyTIFFReader_memcpy_s(tiff->currentFrame.stripbytecounts, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t)); + TinyTIFF_memcpy_s(tiff->currentFrame.stripbytecounts, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t)); } else { tiff->wasError=TINYTIFF_TRUE; TINYTIFF_SET_LAST_ERROR(tiff, "STRIPBYTECOUNTS has an invalid value (==0) or error reading data!\0"); @@ -851,7 +847,7 @@ int TinyTIFFReader_getSampleData_s___internl(TinyTIFFReaderFile* tiff, void* buf } unsigned long stripi=0; for (stripi=sample*tiff->currentFrame.bitspersample/8; stripicurrentFrame.bitspersample/8*tiff->currentFrame.samplesperpixel) { - if (doSizeChecks) TinyTIFFReader_memcpy_s(&(((uint8_t*)buffer)[outputimageidx_bytes]), buffer_size-outputimageidx_bytes, &(stripdata[stripi]), tiff->currentFrame.bitspersample/8); + if (doSizeChecks) TinyTIFF_memcpy_s(&(((uint8_t*)buffer)[outputimageidx_bytes]), buffer_size-outputimageidx_bytes, &(stripdata[stripi]), tiff->currentFrame.bitspersample/8); else memcpy(&(((uint8_t*)buffer)[outputimageidx_bytes]), &(stripdata[stripi]), tiff->currentFrame.bitspersample/8); #ifdef TINYTIFF_ADDITIONAL_DEBUG_MESSAGES if (stripicurrentFrame.bitspersample/8+10*tiff->currentFrame.bitspersample/8*tiff->currentFrame.samplesperpixel) printf(" - memcpy(buffer[%8lu], stripdata[%8lu], %lu)\n", (unsigned long)outputimageidx_bytes, (unsigned long)stripi, (unsigned long)(tiff->currentFrame.bitspersample/8)); diff --git a/src/tinytiffreader.h b/src/tinytiffreader.h index 0e4bc45..453d61f 100644 --- a/src/tinytiffreader.h +++ b/src/tinytiffreader.h @@ -23,10 +23,7 @@ #include "tinytiff_export.h" #include "tinytiff_defs.h" -#include -#include -#include -#include +#include /*! \defgroup tinytiffreader Tiny TIFF reader library diff --git a/src/tinytiffwriter.c b/src/tinytiffwriter.c index d2c85ea..1250167 100644 --- a/src/tinytiffwriter.c +++ b/src/tinytiffwriter.c @@ -22,7 +22,11 @@ #include #include +#include +#include +#include #include "tiff_definitions_internal.h" +#include "tinytiff_ctools_internal.h" #include "tinytiff_version.h" #ifndef __WINDOWS__ @@ -427,7 +431,7 @@ static void TinyTIFFWriter_startIFD(TinyTIFFWriterFile* tiff, int hsize) { tiff->lastHeader=(uint8_t*)calloc(hsize+2, 1); tiff->lastHeaderSize=hsize; } else { - memset(tiff->lastHeader, 0, hsize+2); + TinyTIFF_memset_s(tiff->lastHeader, tiff->lastHeaderSize+2, 0, hsize+2); } tiff->pos=2; } @@ -700,7 +704,7 @@ TinyTIFFWriterFile* TinyTIFFWriter_open(const char* filename, uint16_t bitsPerSa if (!tiff) return NULL; //tiff->file=fopen(filename, "wb"); TinyTIFFWriter_fopen(tiff, filename); - memset(tiff->lastError, 0, TIFF_LAST_ERROR_SIZE); + TinyTIFF_memset_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, 0, TIFF_LAST_ERROR_SIZE); tiff->wasError=TINYTIFF_FALSE; tiff->width=width; tiff->height=height; @@ -810,37 +814,21 @@ void TinyTIFFWriter_close_withdescription(TinyTIFFWriterFile* tiff, const char* if (imageDescription) { #ifdef TINYTIFF_WRITE_COMMENTS if (tiff->descriptionOffset>0) { - const size_t inlen=strlen(imageDescription); + const size_t inlen=TinyTIFF_strlen_s(imageDescription, TINYTIFFWRITER_DESCRIPTION_SIZE); char description[TINYTIFFWRITER_DESCRIPTION_SIZE+1]; - memset(description, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1); + TinyTIFF_memset_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1); if (inlen>0) { if (inlen<=TINYTIFFWRITER_DESCRIPTION_SIZE) { - #ifdef HAVE_STRCPY_S - strcpy_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, imageDescription); - #else - strcpy(description, imageDescription); - #endif + TINYTIFF_STRCPY_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, imageDescription); } else { - #ifdef HAVE_MEMCPY_S - memcpy_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, imageDescription, TINYTIFFWRITER_DESCRIPTION_SIZE); - #else - memcpy(description, imageDescription, TINYTIFFWRITER_DESCRIPTION_SIZE); - #endif + TinyTIFF_memcpy_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, imageDescription, TINYTIFFWRITER_DESCRIPTION_SIZE); } } else { - #ifdef HAVE_SPRINTF_S - sprintf_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\nimages=%ld", (unsigned long)(tiff->frames)); - #else - sprintf(description, "TinyTIFFWriter_version=1.1\nimages=%ld", (unsigned long)(tiff->frames)); - #endif + TINYTIFF_SPRINTF_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\nimages=%ld", (unsigned long)(tiff->frames)); } description[TINYTIFFWRITER_DESCRIPTION_SIZE]='\0'; -#ifdef HAVE_STRNLEN_S - const size_t dlen=strnlen_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1); -#else - const size_t dlen=strlen(description); -#endif + const size_t dlen=TinyTIFF_strlen_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1); //printf("WRITING COMMENT\n***"); //printf(description); @@ -862,64 +850,25 @@ void TinyTIFFWriter_close_withdescription(TinyTIFFWriterFile* tiff, const char* void TinyTIFFWriter_close_withmetadatadescription(TinyTIFFWriterFile* tiff, double pixel_width, double pixel_height, double frametime, double deltaz) { if (tiff) { char description[TINYTIFFWRITER_DESCRIPTION_SIZE+1]; - memset(description, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1); -#ifdef HAVE_SPRINTF_S + TinyTIFF_memset_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1); const int spwlen=256; -#endif char spw[256]; -#ifdef HAVE_SPRINTF_S - sprintf_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\nimages=%lu", (unsigned long int)tiff->frames); -#else - sprintf(description, "TinyTIFFWriter_version=1.1\nimages=%lu", (unsigned long int)tiff->frames); -#endif + TINYTIFF_SPRINTF_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\nimages=%lu", (unsigned long int)tiff->frames); if (fabs(pixel_width)>10.0*DBL_MIN) { -#ifdef HAVE_SPRINTF_S - sprintf_s(spw, spwlen, "\npixel_width=%lf ", pixel_width); -#else - sprintf(spw, "\npixel_width=%lf ", pixel_width); -#endif -#ifdef HAVE_STRCAT_S - strcat_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); -#else - strcat(description,spw); -#endif + TINYTIFF_SPRINTF_S(spw, spwlen, "\npixel_width=%lf ", pixel_width); + TINYTIFF_STRCAT_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); } if (fabs(pixel_height)>10.0*DBL_MIN) { -#ifdef HAVE_SPRINTF_S - sprintf_s(spw, spwlen, "\npixel_height=%lf ", pixel_height); -#else - sprintf(spw, "\npixel_height=%lf ", pixel_height); -#endif -#ifdef HAVE_STRCAT_S - strcat_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); -#else - strcat(description,spw); -#endif + TINYTIFF_SPRINTF_S(spw, spwlen, "\npixel_height=%lf ", pixel_height); + TINYTIFF_STRCAT_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); } if (fabs(deltaz)>10.0*DBL_MIN) { -#ifdef HAVE_SPRINTF_S - sprintf_s(spw, spwlen, "\ndeltaz=%lf ", deltaz); -#else - sprintf(spw, "\ndeltaz=%lf ", deltaz); -#endif -#ifdef HAVE_STRCAT_S - strcat_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); -#else - strcat(description,spw); -#endif + TINYTIFF_SPRINTF_S(spw, spwlen, "\ndeltaz=%lf ", deltaz); + TINYTIFF_STRCAT_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); } if (fabs(frametime)>10.0*DBL_MIN) { -#ifdef HAVE_SPRINTF_S - sprintf_s(spw, spwlen, "\nframetime=%lg ", frametime); -#else - sprintf(spw, "\nframetime=%lg ", frametime); -#endif -#ifdef HAVE_STRCAT_S - strcat_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); -#else - strcat(description,spw); -#endif - + TINYTIFF_SPRINTF_S(spw, spwlen, "\nframetime=%lg ", frametime); + TINYTIFF_STRCAT_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, spw); } description[TINYTIFFWRITER_DESCRIPTION_SIZE]='\0'; TinyTIFFWriter_close_withdescription(tiff, description); @@ -927,33 +876,19 @@ void TinyTIFFWriter_close_withmetadatadescription(TinyTIFFWriterFile* tiff, doub } -#ifdef HAVE_SPRINTF_S #define TINTIFFWRITER_WRITEImageDescriptionTemplate(tiff) \ if (tiff->frames<=0) {\ int datapos=0;\ int sizepos=0;\ char description[TINYTIFFWRITER_DESCRIPTION_SIZE+1];\ - memset(description, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1);\ - sprintf_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\n");\ + TinyTIFF_memset_s(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1);\ + TINYTIFF_STRCPY_S(description, TINYTIFFWRITER_DESCRIPTION_SIZE+1, "TinyTIFFWriter_version=1.1\n");\ description[TINYTIFFWRITER_DESCRIPTION_SIZE]='\0';\ TinyTIFFWriter_writeIFDEntryASCIIARRAY(tiff, TIFF_FIELD_IMAGEDESCRIPTION, description, TINYTIFFWRITER_DESCRIPTION_SIZE, &datapos, &sizepos);\ tiff->descriptionOffset=tiff->lastStartPos+datapos;\ tiff->descriptionSizeOffset=tiff->lastStartPos+sizepos;\ } -#else -#define TINTIFFWRITER_WRITEImageDescriptionTemplate(tiff) \ - if (tiff->frames<=0) {\ - int datapos=0;\ - int sizepos=0;\ - char description[TINYTIFFWRITER_DESCRIPTION_SIZE+1];\ - memset(description, 0, TINYTIFFWRITER_DESCRIPTION_SIZE+1);\ - sprintf(description, "TinyTIFFWriter_version=1.1\n");\ - description[TINYTIFFWRITER_DESCRIPTION_SIZE]='\0';\ - TinyTIFFWriter_writeIFDEntryASCIIARRAY(tiff, TIFF_FIELD_IMAGEDESCRIPTION, description, TINYTIFFWRITER_DESCRIPTION_SIZE, &datapos, &sizepos);\ - tiff->descriptionOffset=tiff->lastStartPos+datapos;\ - tiff->descriptionSizeOffset=tiff->lastStartPos+sizepos;\ - } -#endif + int TinyTIFFWriter_writeImageMultiSample(TinyTIFFWriterFile *tiff, const void *data, enum TinyTIFFSampleLayout inputOrganisation, enum TinyTIFFSampleLayout outputOrganization) { @@ -1050,7 +985,7 @@ int TinyTIFFWriter_writeImageMultiSample(TinyTIFFWriterFile *tiff, const void *d for (sample=0; samplesamples; sample++) { const size_t bytecount=tiff->bitspersample/8; const size_t tmpidx=(sample*tiff->width*tiff->height+pix)*bytecount; - memcpy(&(tmp[tmpidx]), &(((uint8_t*)data)[sampidx]), bytecount); + TinyTIFF_memcpy_s(&(tmp[tmpidx]), bytecount, &(((uint8_t*)data)[sampidx]), bytecount); sampidx++; } } @@ -1067,7 +1002,7 @@ int TinyTIFFWriter_writeImageMultiSample(TinyTIFFWriterFile *tiff, const void *d const size_t bytecount=tiff->bitspersample/8; const size_t tmpidx=(pix*tiff->samples+sample)*bytecount; const size_t sampidx=(sample*tiff->width*tiff->height+pix)*bytecount; - memcpy(&(tmp[tmpidx]), &(((uint8_t*)data)[sampidx]), bytecount); + TinyTIFF_memcpy_s(&(tmp[tmpidx]), bytecount, &(((uint8_t*)data)[sampidx]), bytecount); } } TinyTIFFWriter_fwrite(tmp, tiff->width*tiff->height*tiff->samples*(tiff->bitspersample/8), 1, tiff); diff --git a/src/tinytiffwriter.h b/src/tinytiffwriter.h index 02cad3f..e12a1b2 100644 --- a/src/tinytiffwriter.h +++ b/src/tinytiffwriter.h @@ -26,10 +26,7 @@ #include "tinytiff_export.h" #include "tinytiff_defs.h" -#include -#include -#include -#include +#include /*! \defgroup tinytiffwriter Tiny TIFF writer library \ingroup tinytiff_maingroup diff --git a/tests/tinytiffwriter_test/tinytiffwriter_test.cpp b/tests/tinytiffwriter_test/tinytiffwriter_test.cpp index d7a1876..959dcbc 100644 --- a/tests/tinytiffwriter_test/tinytiffwriter_test.cpp +++ b/tests/tinytiffwriter_test/tinytiffwriter_test.cpp @@ -18,7 +18,7 @@ using namespace std; template -bool libtiffTestRead(const char* filename, const T* writteneven, const T* writtenodd, uint32_t width, uint32_t height, uint16_t samples=1, uint32_t frames_expected=0, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky) { +bool libtiffTestRead(const char* filename, const T* writteneven, const T* writtenodd, uint32_t width, uint32_t height, uint16_t samples=1, uint32_t frames_expected=0, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky, std::string* description_out=nullptr) { bool ok=true; #ifdef TINYTIFF_TEST_LIBTIFF TIFF* tif = TIFFOpen(filename, "r"); @@ -34,7 +34,12 @@ bool libtiffTestRead(const char* filename, const T* writteneven, const T* writte TIFFGetField(tif,TIFFTAG_BITSPERSAMPLE,&bs); char* val=NULL; TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&val); - if (val) std::cout<<" ImageDescription("<clear(); + } TIFFPrintDirectory(tif, stdout); if (nx==width && ny==height && ns==samples && bs==sizeof(T)*8) { size_t errcnt=0; @@ -98,9 +103,14 @@ bool libtiffTestRead(const char* filename, const T* writteneven, const T* writte return ok; } +enum class DescriptionMode { + None, + Text, + Metadata +}; template -void performWriteTest(const std::string& name, const char* filename, const T* imagedata, size_t WIDTH, size_t HEIGHT, size_t SAMPLES, TinyTIFFWriterSampleInterpretation interpret, std::vector& test_results, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky, TinyTIFFSampleLayout outputOrg=TinyTIFF_Chunky) { +void performWriteTest(const std::string& name, const char* filename, const T* imagedata, size_t WIDTH, size_t HEIGHT, size_t SAMPLES, TinyTIFFWriterSampleInterpretation interpret, std::vector& test_results, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky, TinyTIFFSampleLayout outputOrg=TinyTIFF_Chunky, DescriptionMode descMode=DescriptionMode::None) { const size_t bits=sizeof(T)*8; std::string desc=std::to_string(WIDTH)+"x"+std::to_string(HEIGHT)+"pix/"+std::to_string(bits)+"bit/"+std::to_string(SAMPLES)+"ch/1frame"; if (inputOrg==TinyTIFF_Chunky && outputOrg==TinyTIFF_Chunky) desc+="/CHUNKY_FROM_CHUNKY"; @@ -122,15 +132,28 @@ void performWriteTest(const std::string& name, const char* filename, const T* im test_results.back().success=false; TESTFAIL("error writing image data into '"<(filename, imagedata, nullptr, WIDTH, HEIGHT, SAMPLES, 1, inputOrg)) { - test_results.back().success=false; - TESTFAIL("reading '"<(filename, imagedata, nullptr, WIDTH, HEIGHT, SAMPLES, 1, inputOrg, &description_out)) { + test_results.back().success=false; + TESTFAIL("reading '"<