From 80ece1bd3c4c35097d3cd90f30f0b39f603ca2ab Mon Sep 17 00:00:00 2001 From: Mihail Isakov Date: Sun, 14 Aug 2022 04:44:59 +0200 Subject: [PATCH] BUG: fixed memory leaks in MINC IO MINC IO often did not free allocations before thowing an exception, detected by https://github.com/InsightSoftwareConsortium/ITK/pull/3529 --- Modules/IO/MINC/src/itkMINCImageIO.cxx | 49 ++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/Modules/IO/MINC/src/itkMINCImageIO.cxx b/Modules/IO/MINC/src/itkMINCImageIO.cxx index e66e26376a8..224c43e1f79 100644 --- a/Modules/IO/MINC/src/itkMINCImageIO.cxx +++ b/Modules/IO/MINC/src/itkMINCImageIO.cxx @@ -955,6 +955,10 @@ MINCImageIO::WriteImageInformation() if (nDims > 3) { + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } itkExceptionMacro(<< "Unfortunately, only up to 3D volume are supported now."); } @@ -1038,6 +1042,10 @@ MINCImageIO::WriteImageInformation() this->m_MINCPImpl->m_Volume_type = MI_TYPE_DOUBLE; break; default: + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } itkExceptionMacro(<< "Could read datatype " << this->GetComponentType()); } @@ -1165,6 +1173,10 @@ MINCImageIO::WriteImageInformation() mivolumeprops_t hprops; if (minew_volume_props(&hprops) < 0) { + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } itkExceptionMacro(<< "Could not allocate MINC properties"); } @@ -1172,11 +1184,21 @@ MINCImageIO::WriteImageInformation() { if (miset_props_compression_type(hprops, MI_COMPRESS_ZLIB) < 0) { + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not set MINC compression"); } if (miset_props_zlib_compression(hprops, this->GetCompressionLevel()) < 0) { + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not set MINC compression level"); } } @@ -1184,6 +1206,11 @@ MINCImageIO::WriteImageInformation() { if (miset_props_compression_type(hprops, MI_COMPRESS_NONE) < 0) { + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not set MINC compression"); } } @@ -1197,23 +1224,31 @@ MINCImageIO::WriteImageInformation() &this->m_MINCPImpl->m_Volume) < 0) { // Error opening the volume + for (unsigned int i = 0; i < minc_dimensions; ++i) + { + mifree_dimension_handle(this->m_MINCPImpl->m_MincApparentDims[i]); + } + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not open file \"" << m_FileName.c_str() << "\"."); } if (micreate_volume_image(this->m_MINCPImpl->m_Volume) < 0) { // Error opening the volume + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not create image in file \"" << m_FileName.c_str() << "\"."); } if (miset_apparent_dimension_order( this->m_MINCPImpl->m_Volume, minc_dimensions, this->m_MINCPImpl->m_MincApparentDims) < 0) { + mifree_volume_props(hprops); itkExceptionMacro(<< " Can't set apparent dimension order!"); } if (miset_slice_scaling_flag(this->m_MINCPImpl->m_Volume, 0) < 0) { + mifree_volume_props(hprops); itkExceptionMacro(<< "Could not set slice scaling flag"); } @@ -1396,7 +1431,17 @@ MINCImageIO::Write(const void * buffer) delete[] count; itkExceptionMacro(<< "Could not read datatype " << this->GetComponentType()); } - this->WriteImageInformation(); + + try + { + this->WriteImageInformation(); + } + catch (const itk::ExceptionObject & ex) + { + delete[] start; + delete[] count; + throw; + } // by default valid range will be equal to range, to avoid scaling if (volume_data_type == this->m_MINCPImpl->m_Volume_type) @@ -1430,8 +1475,6 @@ MINCImageIO::Write(const void * buffer) delete[] count; itkExceptionMacro(<< " Can not set real value hyperslab!!\n"); } - // TODO: determine what to do if we are streming - this->CloseVolume(); delete[] start; delete[] count;