ITK: Nifti volume of specific size + Shrink filter cause segmentation fault
Description
The combination of NIFTI + Shrink filter causes a segmentation fault for some dimensions and sizes.
Steps to Reproduce (MVE)
-
Generate a nifti volume of the size (1034, 1034, 1020)
import itk pixel_type = itk.US dimension = 3 image_type = itk.Image[pixel_type, dimension] start = itk.Index[dimension]() start.Fill(0) size = itk.Size[dimension]() size[0] = 1034 size[1] = 1034 size[2] = 1020 region = itk.ImageRegion[dimension]() region.SetIndex(start) region.SetSize(size) image = image_type.New(Regions=region) image.Allocate() itk.imwrite(image, "segmentation-fault-test.nii") -
Create a pipeline with
ImageFileReader+ShrinkImageFilterand update at the endimport itk from itk import ShrinkImageFilter image_path = "segmentation-fault-test" reader = itk.ImageFileReader.New(FileName=image_path) shrink = ShrinkImageFilter.New(reader) shrink.SetShrinkFactors(4) print("Update") shrink.Update() print("GetOutput") data = shrink.GetOutput() del shrink del reader print("Done") -
Run it (for windows add
-Xfaulthandlerto the python command)
Expected behavior
Script runs through without any errors and outputs all print messages.
Actual behavior
A segmentation fault (linux) / access violation (windows) after the “Update” printout.
Reproducibility
With the mentioned dimensions 100%.
Versions/Environments
Linux:
- itk 5.1.2 and 5.2.1
- Python 3.8
Windows:
- itk 5.3rc4.post2
- Python 3.9
Additional Information
- The dimensions matter, e.g.
1034, 1034, 1020(1090539120) crash4048, 2048, 132(1094320128) works826, 843, 3314(2307597852) crash
- Other voxel types uint8 (with
1034, 1034, 2040) or float are also affected - Seems to be related to the byte size in combination with the dimensions
- Other shrink factors (as
2) are also affected .nii.gzis also affectednrrdseems to work FINE- In some other workflow this causes a corruption of the volume without a seg fault (I try to add a picture later)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 22 (21 by maintainers)
After a big of digging I think I found the bug in the upstream nifti_clib in
nifti_read_subregion_image. The requested size of1029 * 1029 * 1017 * 2 = 2 153 682 594 bytesis bigger than the signed size of a int causing an overflow. https://github.com/InsightSoftwareConsortium/ITK/blob/2f2b29cbbe3fe91474933e0194db8d581d5b3247/Modules/ThirdParty/NIFTI/src/nifti/niftilib/nifti1_io.c#L6972 The followingmallocdoes not allocate any memory and thus causes a segmentation fault. https://github.com/InsightSoftwareConsortium/ITK/blob/2f2b29cbbe3fe91474933e0194db8d581d5b3247/Modules/ThirdParty/NIFTI/src/nifti/niftilib/nifti1_io.c#L7060ShrinkImageFilterhas had some problems for a long time now. Fixing the crashes using this repro case would be useful for large images, as sometimes people don’t do a proper pyramid and resort toShrinkImageFilter.Great job so far!
A small addition: There are cases, where the data only gets corrupted and does not crash on loading. The image below is suppose to be a cylinder and the blocky part in the middle is “corrupted”. This is visualized with itkwidgets and only has a fault on later use.
size: (826, 843, 3314), type: unsigned_shortIt crashes in nifti reader, when trying to read a region with index 3,3,2 and size 1029,1029,1017.
I was able to reproduce the issue in C++: