diff --git a/Modules/IO/PNG/include/itkPNGImageIO.h b/Modules/IO/PNG/include/itkPNGImageIO.h index 3ee680644c5..525781d3e16 100644 --- a/Modules/IO/PNG/include/itkPNGImageIO.h +++ b/Modules/IO/PNG/include/itkPNGImageIO.h @@ -114,7 +114,7 @@ class ITKIOPNG_EXPORT PNGImageIO : public ImageIOBase PrintSelf(std::ostream & os, Indent indent) const override; void - WriteSlice(const std::string & fileName, const void * buffer); + WriteSlice(const std::string & fileName, const void * const buffer); PaletteType m_ColorPalette; diff --git a/Modules/IO/PNG/src/itkPNGImageIO.cxx b/Modules/IO/PNG/src/itkPNGImageIO.cxx index 309c57f5b8f..f62b0d6ac21 100644 --- a/Modules/IO/PNG/src/itkPNGImageIO.cxx +++ b/Modules/IO/PNG/src/itkPNGImageIO.cxx @@ -21,39 +21,21 @@ #include #include -namespace itk -{ extern "C" { - /* The PNG library does not expect the error function to return. - Therefore we must use this ugly longjmp call. */ void itkPNGWriteErrorFunction(png_structp png_ptr, png_const_charp itkNotUsed(error_msg)) { longjmp(png_jmpbuf(png_ptr), 1); } -} -extern "C" -{ void itkPNGWriteWarningFunction(png_structp itkNotUsed(png_ptr), png_const_charp itkNotUsed(warning_msg)) {} } -namespace -{ -// Wrap setjmp call to avoid warnings about variable clobbering. -bool -wrapSetjmp(png_structp & png_ptr) +namespace itk { - if (setjmp(png_jmpbuf(png_ptr))) - { - return true; - } - return false; -} -} // namespace // simple class to call fopen on construct and // fclose on destruct @@ -74,7 +56,7 @@ class PNGFileWrapper } } - FILE * m_FilePointer; + FILE * volatile m_FilePointer; }; bool @@ -180,10 +162,10 @@ PNGImageIO::Read(void * buffer) itkExceptionMacro("File is not png type " << this->GetFileName()); } - if (wrapSetjmp(png_ptr)) + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - itkExceptionMacro("File is not png type " << this->GetFileName()); + itkExceptionMacro("PNG critical error in " << this->GetFileName()); } png_init_io(png_ptr, fp); @@ -371,6 +353,12 @@ PNGImageIO::ReadImageInformation() return; } + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + itkExceptionMacro("PNG critical error in " << this->GetFileName()); + } + png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); @@ -511,7 +499,7 @@ PNGImageIO::Write(const void * buffer) } void -PNGImageIO::WriteSlice(const std::string & fileName, const void * buffer) +PNGImageIO::WriteSlice(const std::string & fileName, const void * const buffer) { // use this class so return will call close PNGFileWrapper pngfp(fileName.c_str(), "wb"); @@ -571,7 +559,7 @@ PNGImageIO::WriteSlice(const std::string & fileName, const void * buffer) png_init_io(png_ptr, fp); png_set_error_fn(png_ptr, (png_voidp) nullptr, itkPNGWriteErrorFunction, itkPNGWriteWarningFunction); - if (wrapSetjmp(png_ptr)) + if (setjmp(png_jmpbuf(png_ptr))) { itkExceptionMacro("Error while writing Slice to file: " << this->GetFileName() << std::endl << "Reason: " << itksys::SystemTools::GetLastSystemError()); diff --git a/Modules/IO/PNG/test/CMakeLists.txt b/Modules/IO/PNG/test/CMakeLists.txt index 229222eb51d..d6556f69213 100644 --- a/Modules/IO/PNG/test/CMakeLists.txt +++ b/Modules/IO/PNG/test/CMakeLists.txt @@ -80,3 +80,7 @@ itk_add_test(NAME itkPNGImageIOTest3GreyPaletteExpandedGrey itk_add_test(NAME itkPNGImageIOTestCorrupt COMMAND ITKIOPNGTestDriver itkPNGImageIOTest3 DATA{Input/cthead1-257-corrupt.png}) + +itk_add_test(NAME itkPNGImageIOTestCorrupt2 + COMMAND ITKIOPNGTestDriver + itkPNGImageIOTest3 DATA{Input/corrupted.png}) diff --git a/Modules/IO/PNG/test/Input/corrupted.png.sha512 b/Modules/IO/PNG/test/Input/corrupted.png.sha512 new file mode 100644 index 00000000000..35eb228c32f --- /dev/null +++ b/Modules/IO/PNG/test/Input/corrupted.png.sha512 @@ -0,0 +1 @@ +36007c21373bde578b0c87295b7b9c948fbd5c251c9a22b0f58d1a34e0645ff9030e6a52d3d10c3a69c10f2e1af93dcdf7976a7ad4bd6551b05ad914c7199d5b