Skip to content

COMP: Fix nightly compiler warnings and a CumulativeGaussianOptimizer use-after-free#6457

Open
hjmjohnson wants to merge 5 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:fix-deprecated-copy-special-members
Open

COMP: Fix nightly compiler warnings and a CumulativeGaussianOptimizer use-after-free#6457
hjmjohnson wants to merge 5 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:fix-deprecated-copy-special-members

Conversation

@hjmjohnson

Copy link
Copy Markdown
Member

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
Commit Kind Diagnostic Classes
Rule of Zero drop redundant non-virtual =default destructors -Wdeprecated-copy-with-(user-provided-)dtor RealTimeInterval, ConstSparseFieldLayerIterator, ObjectStore::MemoryBlock
Rule of Five default copy/move on polymorphic bases (must keep the virtual dtor) -Wdeprecated-copy-with-(user-provided-)dtor ImageBoundaryCondition, ResourceProbe, TimeProbe, FlatStructuringElement, MultivariateLegendrePolynomial, TemporalRegion
Bound loops by ImageDimension GCC could not prove the runtime component count ≤ the fixed array size -Waggressive-loop-optimizations WarpImageFilter, ESMDemonsRegistrationFunction
Rule of Three default copy-assignment alongside the user-declared copy ctor -Wdeprecated-copy TBBImageRegionSplitter
BUG reset member after freeing the storage it aliases -Wlifetime-safety-invalidation CumulativeGaussianOptimizer
The use-after-free (BUG commit)

CumulativeGaussianOptimizer::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. The fix
resets the member to nullptr once its storage is freed.

Warnings deliberately left unaddressed
  • 6 other -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; the return std::move() remedy risks -Wredundant-move elsewhere.
  • -Wzero-as-null-pointer-constant / -Wnrvo in pocketfft_hdronly.h: vendored third-party; belongs upstream.
Verification

Affected libraries compiled clean on AppleClang via a configured build
tree; WarpImageFilter, ESMDemons, and CumulativeGaussian tests
pass. TBBImageRegionSplitter compiles only when Module_ITKTBB is
enabled (not in the local tree) and was verified by inspection.
pre-commit passes on every commit.

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.
@github-actions github-actions Bot added type:Compiler Compiler support or related warnings area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:Registration Issues affecting the Registration module area:Video Issues affecting the Video module area:Numerics Issues affecting the Numerics module labels Jun 17, 2026
@hjmjohnson hjmjohnson marked this pull request as ready for review June 17, 2026 02:50
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes nightly CDash compiler warnings (-Wdeprecated-copy-with-user-provided-dtor, -Waggressive-loop-optimizations, -Wdeprecated-copy) across 14 files and patches one real use-after-free in CumulativeGaussianOptimizer surfaced by Clang's experimental lifetime-safety pass.

  • Rule of Zero/Five/Three — drops redundant non-virtual = default destructors where Rule of Zero applies, and explicitly adds copy/move special members alongside user-declared virtual destructors on polymorphic bases (ImageBoundaryCondition, ResourceProbe, TimeProbe, FlatStructuringElement, MultivariateLegendrePolynomial, TemporalRegion); also adds the missing copy-assignment to TBBImageRegionSplitter.
  • Loop bounds — replaces runtime-variable component counts with compile-time ImageDimension in WarpImageFilter and ESMDemonsRegistrationFunction; safe because VerifyInputInformation() enforces equality and SetLength initializes the arrays to exactly ImageDimension slots.
  • Use-after-free — after delete derivative; in StartOptimization(), sets m_CumulativeGaussianArray = nullptr to prevent PrintSelf() from dereferencing the freed memory through the now-dangling alias.

Confidence Score: 5/5

Safe to merge; all changes are mechanical warning suppressions or a well-scoped one-liner bug fix with no functional side effects on the hot paths.

The UAF fix is minimal and correct — it resets the dangling alias immediately after the delete, and PrintSelf already guards on null. The loop-bound substitutions are semantically equivalent because VerifyInputInformation() enforces the invariant at runtime and SetLength initialises the arrays to exactly ImageDimension slots before the loops. Every Rule of Zero/Five/Three change involves only classes whose members are standard library value types or pointers managed elsewhere, so the defaulted specials cannot introduce double-free or shallow-copy hazards.

No files require special attention; the CumulativeGaussianOptimizer source is the most semantically significant change but it is a one-liner with clear pre- and post-conditions.

Important Files Changed

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

@hjmjohnson hjmjohnson requested a review from dzenanz June 17, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:Numerics Issues affecting the Numerics module area:Registration Issues affecting the Registration module area:Video Issues affecting the Video module type:Compiler Compiler support or related warnings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant