COMP: Fix nightly compiler warnings and a CumulativeGaussianOptimizer use-after-free#6457
Conversation
Clang reports -Wdeprecated-copy-with-(user-provided-)dtor where a class declares a do-nothing destructor but relies on the implicitly defaulted copy operations. For non-polymorphic classes the cleanest fix is to drop the redundant destructor entirely so the compiler implicitly generates all special members. Removes the defaulted/empty destructor from RealTimeInterval (and its out-of-line definition), the ConstSparseFieldLayerIterator iterator, and the ObjectStore::MemoryBlock helper.
Clang reports -Wdeprecated-copy-with-(user-provided-)dtor where a class declares a destructor but relies on the implicitly defaulted copy operations. These classes are polymorphic bases that must keep their virtual destructor, so rule-of-zero does not apply; instead explicitly default all copy and move special members (rule of five). Affects ImageBoundaryCondition, ResourceProbe, TimeProbe, FlatStructuringElement, MultivariateLegendrePolynomial, and TemporalRegion.
GCC -Waggressive-loop-optimizations reports "iteration N invokes undefined behavior" because the loop bound, a runtime component count from NumericTraits::GetLength, is not provably less than or equal to the fixed ImageDimension size of the point/update array being indexed. The count equals ImageDimension by construction (SetLength sizes the field to ImageDimension; WarpImageFilter::VerifyInputInformation also enforces it), and the surrounding loops already iterate to ImageDimension. Use the compile-time constant directly, giving the compiler a provable bound and matching the rest of each file.
The TBB splitter declares a copy constructor (required by tbb) but relies on the implicitly defaulted copy-assignment operator it uses via *this = region, which Clang deprecates under -Wdeprecated-copy. Complete the rule of three by explicitly defaulting the copy-assignment operator. Compiled only when Module_ITKTBB is enabled, which the local build tree does not configure; verified by inspection.
StartOptimization() points m_CumulativeGaussianArray at a locally allocated derivative array, then deletes that array before returning, leaving the member dangling. PrintSelf() dereferences the member when it is non-null, so printing the optimizer after optimization is a use-after-free. Reset the member to nullptr once its storage is freed. Found by Clang -Wlifetime-safety-invalidation.
|
| Filename | Overview |
|---|---|
| Modules/Numerics/Optimizers/src/itkCumulativeGaussianOptimizer.cxx | Correct UAF fix: m_CumulativeGaussianArray = nullptr after freeing derivative prevents PrintSelf from dereferencing the dangling alias. |
| Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx | Loop bound changed from runtime numberOfDisplacementComponents to compile-time ImageDimension; safe because VerifyInputInformation() enforces equality and SetLength initialises the array to exactly ImageDimension. |
| Modules/Registration/PDEDeformable/include/itkESMDemonsRegistrationFunction.hxx | Same loop-bound fix as WarpImageFilter; all three changed loops access PixelType arrays that are explicitly SetLength'd to ImageDimension. |
| Modules/Core/Common/src/itkTBBMultiThreader.cxx | Adds defaulted copy-assignment to TBBImageRegionSplitter alongside the existing user-declared copy constructor, completing Rule of Three and silencing -Wdeprecated-copy. |
| Modules/Core/Common/include/itkImageBoundaryCondition.h | Adds explicitly defaulted copy/move members to polymorphic base; no raw-pointer members, so defaults are semantically correct. |
| Modules/Core/Common/include/itkObjectStore.h | Removes redundant = default destructor on MemoryBlock (Rule of Zero); design intent preserved in a comment on the Begin member. |
| Modules/Numerics/Polynomials/include/itkMultivariateLegendrePolynomial.h | Adds defaulted copy/move alongside the virtual destructor; all private members are std::vector or primitive types, so defaults are safe. |
| Modules/Video/Core/include/itkTemporalRegion.h | Adds defaulted copy/move alongside the user-defined destructor override; all members are value types, so defaults are safe. |
| Modules/Core/Common/include/itkResourceProbe.h | Adds explicitly defaulted copy/move alongside the virtual destructor on this polymorphic base; silences -Wdeprecated-copy-with-user-provided-dtor. |
| Modules/Core/Common/include/itkTimeProbe.h | Same Rule of Five treatment as ResourceProbe; safe because TimeProbe holds no unmanaged resources beyond what its bases own. |
| Modules/Core/Common/include/itkRealTimeInterval.h | Drops declaration-only ~RealTimeInterval() (Rule of Zero); corresponding = default definition removed from the .cxx. |
| Modules/Core/Common/src/itkRealTimeInterval.cxx | Removes the = default destructor definition that accompanies the header removal; no other changes. |
| Modules/Core/Common/include/itkSparseFieldLayer.h | Drops redundant = default destructor from ConstSparseFieldLayerIterator; no resources owned, Rule of Zero applies. |
| Modules/Filtering/MathematicalMorphology/include/itkFlatStructuringElement.h | Adds defaulted copy/move alongside the override = default virtual destructor; FlatStructuringElement holds no raw pointers beyond what Neighborhood manages with std::vector. |
Reviews (1): Last reviewed commit: "BUG: Clear dangling m_CumulativeGaussian..." | Re-trigger Greptile
Fixes nightly-CDash compiler warnings, plus one real use-after-free the experimental Clang lifetime pass surfaced. Five commits grouped by kind of change.
What changed, per commit
=defaultdestructors-Wdeprecated-copy-with-(user-provided-)dtorRealTimeInterval,ConstSparseFieldLayerIterator,ObjectStore::MemoryBlock-Wdeprecated-copy-with-(user-provided-)dtorImageBoundaryCondition,ResourceProbe,TimeProbe,FlatStructuringElement,MultivariateLegendrePolynomial,TemporalRegionImageDimension-Waggressive-loop-optimizationsWarpImageFilter,ESMDemonsRegistrationFunction-Wdeprecated-copyTBBImageRegionSplitter-Wlifetime-safety-invalidationCumulativeGaussianOptimizerThe use-after-free (BUG commit)
CumulativeGaussianOptimizer::StartOptimization()pointsm_CumulativeGaussianArrayat a locally allocatedderivativearray,then
deletes that array before returning — leaving the memberdangling.
PrintSelf()dereferences the member when it is non-null, soprinting the optimizer after optimization is a use-after-free. The fix
resets the member to
nullptronce its storage is freed.Warnings deliberately left unaddressed
-Wlifetime-safety-invalidation(StringTools, DOMNode, NrrdImageIO, VTIImageIO, PhilipsPAR): false positives of an experimental, unstable diagnostic — returning/appending to reference parameters is correct C++.-Wnrvo: pedantic optimization hints in multi-return functions; thereturn std::move()remedy risks-Wredundant-moveelsewhere.-Wzero-as-null-pointer-constant/-Wnrvoinpocketfft_hdronly.h: vendored third-party; belongs upstream.Verification
Affected libraries compiled clean on AppleClang via a configured build
tree;
WarpImageFilter,ESMDemons, andCumulativeGaussiantestspass.
TBBImageRegionSplittercompiles only whenModule_ITKTBBisenabled (not in the local tree) and was verified by inspection.
pre-commitpasses on every commit.