From f37853fa4f2bbbc60d2fa00f01aaedd8be158767 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Fri, 23 Jun 2017 16:36:42 +0200 Subject: [PATCH] COMP: Fixed leak into user code Also on behalf of my colleague Floris Berendsen Discussed at http://public.kitware.com/pipermail/insight-developers/2017-June/025206.html With encouraging feedback from Bradley Lowekamp :-) Change-Id: I698cbbf66cf6d3c22a3102a3185700da4bf85f2d --- Modules/IO/NIFTI/include/itkNiftiImageIO.h | 25 +++++++++++- Modules/IO/NIFTI/itk-module.cmake | 3 +- Modules/IO/NIFTI/src/itkNiftiImageIO.cxx | 44 +++++++++++++++++++++- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Modules/IO/NIFTI/include/itkNiftiImageIO.h b/Modules/IO/NIFTI/include/itkNiftiImageIO.h index 2a7f949f2ec..002b87449dd 100644 --- a/Modules/IO/NIFTI/include/itkNiftiImageIO.h +++ b/Modules/IO/NIFTI/include/itkNiftiImageIO.h @@ -23,7 +23,6 @@ #include #include "itkImageIOBase.h" -#include namespace itk { @@ -128,7 +127,29 @@ class ITKIONIFTI_EXPORT NiftiImageIO:public ImageIOBase void SetImageIOMetadataFromNIfTI(); - nifti_image *m_NiftiImage; + //This proxy class provides a nifti_image pointer interface to the internal implementation + //of itk::NiftiImageIO, while hiding the niftilib interface from the external ITK interface. + class NiftiImageProxy; + + //This class has ownership of the proxy and is thereby holder of the nifti_image pointer. + class NiftiImageHolder + { + private: + NiftiImageProxy* const m_NiftiImageProxy; + public: + NiftiImageHolder(); + ~NiftiImageHolder(); + NiftiImageProxy& GetNiftiImageProxy(); + + private: + NiftiImageHolder(const NiftiImageHolder&) ITK_DELETED_FUNCTION; + NiftiImageHolder& operator=(const NiftiImageHolder &) ITK_DELETED_FUNCTION; + }; + + //Note that it is essential that m_NiftiImageHolder is defined before m_NiftiImage, to ensure that + //m_NiftiImage can directly get a proxy from m_NiftiImageHolder during NiftiImageIO construction. + NiftiImageHolder m_NiftiImageHolder; + NiftiImageProxy& m_NiftiImage; double m_RescaleSlope; double m_RescaleIntercept; diff --git a/Modules/IO/NIFTI/itk-module.cmake b/Modules/IO/NIFTI/itk-module.cmake index 09a752f0d8b..114cb91d315 100644 --- a/Modules/IO/NIFTI/itk-module.cmake +++ b/Modules/IO/NIFTI/itk-module.cmake @@ -3,11 +3,10 @@ set(DOCUMENTATION "This modules contains an ImageIO class to read or write the itk_module(ITKIONIFTI ENABLE_SHARED - DEPENDS - ITKNIFTI PRIVATE_DEPENDS ITKIOImageBase ITKTransform + ITKNIFTI TEST_DEPENDS ITKTestKernel ITKNIFTI diff --git a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx index 85b98de240c..f6c9682c2d3 100644 --- a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx +++ b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx @@ -19,6 +19,7 @@ #include "itkIOCommon.h" #include "itkMetaDataObject.h" #include "itkSpatialOrientationAdapter.h" +#include namespace itk { @@ -389,8 +390,47 @@ ::GenerateStreamableReadRegionFromRequestedRegion(const ImageIORegion & requeste return requestedRegion; } -NiftiImageIO::NiftiImageIO(): - m_NiftiImage(ITK_NULLPTR), + +//This internal proxy class provides a pointer-like interface to a nifti_image*, by supporting +//conversions between proxy and nifti_image pointer and arrow syntax (e.g., m_NiftiImage->data). +class NiftiImageIO::NiftiImageProxy +{ + nifti_image* m_ptr; +public: + NiftiImageProxy(nifti_image* ptr) : + m_ptr(ptr) + { + } + + operator nifti_image*() + { + return m_ptr; + } + + nifti_image* operator->() + { + return m_ptr; + } +}; + +NiftiImageIO::NiftiImageHolder::NiftiImageHolder() : +m_NiftiImageProxy(new NiftiImageProxy(ITK_NULLPTR)) +{ +} + +NiftiImageIO::NiftiImageHolder::~NiftiImageHolder() +{ + delete m_NiftiImageProxy; +} + +NiftiImageIO::NiftiImageProxy& NiftiImageIO::NiftiImageHolder::GetNiftiImageProxy() +{ + return *m_NiftiImageProxy; +} + + +NiftiImageIO::NiftiImageIO() : + m_NiftiImage(m_NiftiImageHolder.GetNiftiImageProxy()), m_RescaleSlope(1.0), m_RescaleIntercept(0.0), m_OnDiskComponentType(UNKNOWNCOMPONENTTYPE),