diff --git a/src/tinytiffwriter.c b/src/tinytiffwriter.c index 1250167..82cd2dd 100644 --- a/src/tinytiffwriter.c +++ b/src/tinytiffwriter.c @@ -51,6 +51,9 @@ #ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO # include # warning COMPILING TinyTIFFWriter with WinAPI +# define TinyTIFFWriter_POSTYPE DWORD +#else +# define TinyTIFFWriter_POSTYPE fpos_t #endif // TINYTIFF_USE_WINAPI_FOR_FILEIO @@ -61,6 +64,7 @@ int TinyTIFFWriter_getMaxDescriptionTextSize() { return TINYTIFFWRITER_DESCRIPTION_SIZE; } + /** \defgroup tinytiffwriter_internal TinyTIFFWriter: Internal functions * \ingroup tinytiffwriter */ @@ -212,7 +216,7 @@ static size_t TinyTIFFWriter_fwrite(const void * ptr, size_t size, size_t count, \ingroup tinytiffwriter_internal \internal */ -static long int TinyTIFFWriter_ftell ( TinyTIFFWriterFile * tiff ) { +static long long TinyTIFFWriter_ftell ( TinyTIFFWriterFile * tiff ) { #ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO DWORD dwPtr = SetFilePointer( tiff->hFile, 0, @@ -224,6 +228,18 @@ DWORD dwPtr = SetFilePointer( tiff->hFile, #endif } +int TinyTIFFWriter_fgetpos(TinyTIFFWriterFile* tiff, TinyTIFFWriter_POSTYPE* pos) { +#ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO + *pos= SetFilePointer( tiff->hFile, + 0, + NULL, + FILE_CURRENT ); + return 0; +#else + return fgetpos(tiff->file, pos); +#endif // TINYTIFF_USE_WINAPI_FOR_FILEIO +} + /*! \brief wrapper around fseek \ingroup tinytiffwriter_internal @@ -243,25 +259,6 @@ static int TinyTIFFWriter_fseek_set(TinyTIFFWriterFile* tiff, size_t offset) { #endif // TINYTIFF_USE_WINAPI_FOR_FILEIO } -#ifdef TinyTIFFWriter_fseek_cur // Silence "unused" warning -/*! \brief wrapper around fseek(..., FILE_CURRENT) - \ingroup tinytiffwriter_internal - \internal - */ -static int TinyTIFFWriter_fseek_cur(TinyTIFFWriterFile* tiff, size_t offset) { -#ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO - DWORD res = SetFilePointer (tiff->hFile, - offset, - NULL, - FILE_CURRENT); - - - return res; -#else - return fseek(tiff->file, (long)offset, SEEK_CUR); -#endif // TINYTIFF_USE_WINAPI_FOR_FILEIO -} -#endif /*! \brief calculates the number of channels, covered by the photometric interpretation. If samples is larger than this, the difference are extraSamples! \ingroup tinytiffwriter_internal @@ -901,6 +898,7 @@ int TinyTIFFWriter_writeImageMultiSample(TinyTIFFWriterFile *tiff, const void *d return TINYTIFF_FALSE; } const long pos=TinyTIFFWriter_ftell(tiff); + int hsize=TIFF_HEADER_SIZE; #ifdef TINYTIFF_WRITE_COMMENTS if (tiff->frames<=0) { @@ -973,6 +971,17 @@ int TinyTIFFWriter_writeImageMultiSample(TinyTIFFWriterFile *tiff, const void *d } TinyTIFFWriter_writeIFDEntrySHORT(tiff, TIFF_FIELD_SAMPLEFORMAT, tiff->sampleformat); TinyTIFFWriter_endIFD(tiff, hsize); + + TinyTIFFWriter_POSTYPE datapos=0; TinyTIFFWriter_fgetpos(tiff, &datapos); + const TinyTIFFWriter_POSTYPE data_size_expected=tiff->width*tiff->height*tiff->samples*(tiff->bitspersample/8); + const TinyTIFFWriter_POSTYPE expected_endpos=datapos+data_size_expected; + const TinyTIFFWriter_POSTYPE max_endpos=(((TinyTIFFWriter_POSTYPE)0xFFFFFFFF)-(TinyTIFFWriter_POSTYPE)1024); + if (expected_endpos>=max_endpos) { + tiff->wasError=TINYTIFF_TRUE; + TINYTIFF_SET_LAST_ERROR(tiff, "trying to write behind end of file in TinyTIFFWriter_writeImage() (i.e. too many of a too big frame)\0"); + return TINYTIFF_FALSE; + } + if (inputOrganisation==outputOrganization) { TinyTIFFWriter_fwrite(data, tiff->width*tiff->height*tiff->samples*(tiff->bitspersample/8), 1, tiff); } else if (inputOrganisation==TinyTIFF_Interleaved && outputOrganization==TinyTIFF_Separate) { diff --git a/tests/tinytiffreader_test/tinytiffreader_test.cpp b/tests/tinytiffreader_test/tinytiffreader_test.cpp index 75a01c4..1a20b04 100644 --- a/tests/tinytiffreader_test/tinytiffreader_test.cpp +++ b/tests/tinytiffreader_test/tinytiffreader_test.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/tinytiffwriter_test/tinytiffwriter_test.cpp b/tests/tinytiffwriter_test/tinytiffwriter_test.cpp index f610327..0ea951a 100644 --- a/tests/tinytiffwriter_test/tinytiffwriter_test.cpp +++ b/tests/tinytiffwriter_test/tinytiffwriter_test.cpp @@ -167,6 +167,94 @@ void performWriteTest(const std::string& name, const char* filename, const T* im } } +template +void performWriteTest_ExpectedToFail(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) { + 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"; + if (inputOrg==TinyTIFF_Chunky && outputOrg==TinyTIFF_Planar) desc+="/PLANAR_FROM_CHUNKY"; + if (inputOrg==TinyTIFF_Planar && outputOrg==TinyTIFF_Chunky) desc+="/CHUNKY_FROM_PLANAR"; + if (inputOrg==TinyTIFF_Planar && outputOrg==TinyTIFF_Planar) desc+="/PLANAR_FROM_PLANAR"; + test_results.emplace_back(); + test_results.back().name=name+" ["+desc+", "+std::string(filename)+"]"; + test_results.back().success=true; + std::cout<<"\n\n*****************************************************************************\n"; + std::cout<<"* "<().format, SAMPLES, WIDTH,HEIGHT, interpret); + if (tiff) { + int res; + res=TinyTIFFWriter_writeImageMultiSample(tiff, imagedata, inputOrg, outputOrg); + if (res!=TINYTIFF_FALSE) { + test_results.back().success=false; + TESTFAIL("could not prevent writing image data into '"< WRITING GENERATED ERROR MESSAGE:"< SUCCESSFUL, duration="< FAILED\n"; + } +} + + +template +void performMultiFrameWriteTest_ExpectedToFail(const std::string& name, const char* filename, const T* imagedata, const T* imagedatai, size_t WIDTH, size_t HEIGHT, size_t SAMPLES, size_t FRAMES, TinyTIFFWriterSampleInterpretation interpret, std::vector& test_results, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky, TinyTIFFSampleLayout outputOrg=TinyTIFF_Chunky) { + 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"; + if (inputOrg==TinyTIFF_Chunky && outputOrg==TinyTIFF_Planar) desc+="/PLANAR_FROM_CHUNKY"; + if (inputOrg==TinyTIFF_Planar && outputOrg==TinyTIFF_Chunky) desc+="/CHUNKY_FROM_PLANAR"; + if (inputOrg==TinyTIFF_Planar && outputOrg==TinyTIFF_Planar) desc+="/PLANAR_FROM_PLANAR"; + test_results.emplace_back(); + test_results.back().name=name+" ["+desc+", "+std::string(filename)+"]"; + test_results.back().success=true; + std::cout<<"\n\n*****************************************************************************\n"; + std::cout<<"* "<().format, SAMPLES, WIDTH,HEIGHT, interpret); + if (tiff) { + int res; + size_t f=0; + for (; f WRITING GENERATED ERROR MESSAGE for frame "<<(f+1)<<"/"< SUCCESSFUL, duration="< FAILED\n"; + } +} + template void performMultiFrameWriteTest(const std::string& name, const char* filename, const T* imagedata, const T* imagedatai, size_t WIDTH, size_t HEIGHT, size_t SAMPLES, size_t FRAMES, TinyTIFFWriterSampleInterpretation interpret, std::vector& test_results, TinyTIFFSampleLayout inputOrg=TinyTIFF_Chunky, TinyTIFFSampleLayout outputOrg=TinyTIFF_Chunky) { const size_t bits=sizeof(T)*8; @@ -324,6 +412,13 @@ int main(int argc, char *argv[]) { performWriteTest("WRITING 64-Bit UINT GREY TIFF", "test64.tif", image64.data(), WIDTH, HEIGHT, 1, TinyTIFFWriter_Greyscale, test_results); if (quicktest==TINYTIFF_FALSE) performMultiFrameWriteTest("WRITING 64-Bit UINT GREY TIFF", "test64m.tif", image64.data(), image64i.data(), WIDTH, HEIGHT, 1, NUMFRAMES, TinyTIFFWriter_Greyscale, test_results); + if (quicktest==TINYTIFF_FALSE) { + const size_t WIDTH_too_many=8000; + const size_t HEIGHT_too_many=4000; + const std::vector image64_too_many(WIDTH_too_many*HEIGHT_too_many, 0); + const size_t too_many_frames=((size_t)0xFFFFFFFF)/((size_t)(WIDTH_too_many*HEIGHT_too_many*sizeof(uint64_t)))*8; + performMultiFrameWriteTest_ExpectedToFail("WRITING TOO MANY 64-Bit UINT GREY TIFF", "test64m_toomany.tif", image64_too_many.data(), image64_too_many.data(), WIDTH_too_many, HEIGHT_too_many, 1, too_many_frames, TinyTIFFWriter_Greyscale, test_results); + } performWriteTest("WRITING 32-Bit FLOAT GREY TIFF", "testf.tif", imagef.data(), WIDTH, HEIGHT, 1, TinyTIFFWriter_Greyscale, test_results); if (quicktest==TINYTIFF_FALSE) performMultiFrameWriteTest("WRITING 32-Bit FLOAT GREY TIFF", "testfm.tif", imagef.data(), imagefi.data(), WIDTH, HEIGHT, 1, NUMFRAMES, TinyTIFFWriter_Greyscale, test_results);