From 6262cecb6db68a7467894f134ac2b811f9f625be Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Tue, 22 Sep 2026 08:43:00 -0500 Subject: [PATCH 1/2] BUG: Return from the REJECT_COMPLEX path instead of calling exit() nifti_image_read() ended the calling process with exit(13) when it met a complex datatype, leaking the open file and hfile on the way out. A library reports the condition to its caller: the block now frees the image, closes the file, releases hfile and returns NULL, which is how every other rejection in the function behaves. The message also loses its "64", which was wrong for the 128 and 256 cases. REJECT_COMPLEX is off by default but is supported: -DFSLSTYLE:BOOL=ON turns it on, and nifti2/Makefile defines it always. --- nifti2/nifti2_io.c | 11 +++++++---- niftilib/nifti1_io.c | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/nifti2/nifti2_io.c b/nifti2/nifti2_io.c index 70c136e8..8aa80c2a 100644 --- a/nifti2/nifti2_io.c +++ b/nifti2/nifti2_io.c @@ -6043,10 +6043,13 @@ nifti_image *nifti_image_read( const char *hname , int read_data ) #ifdef REJECT_COMPLEX if ((nim->datatype == DT_COMPLEX64) || (nim->datatype == DT_COMPLEX128) || (nim->datatype == DT_COMPLEX256)) { - fprintf(stderr,"Image Exception Unsupported datatype (COMPLEX64): use fslcomplex to manipulate: %s\n", hname); - exit(13); - } - #endif + fprintf(stderr,"Image Exception Unsupported datatype (COMPLEX): use fslcomplex to manipulate: %s\n", hname); + nifti_image_free(nim); + znzclose(fp); + free(hfile); + return NULL; + } + #endif if( g_opts.debug > 3 ){ fprintf(stderr,"+d nifti_image_read(), have nifti image:\n"); diff --git a/niftilib/nifti1_io.c b/niftilib/nifti1_io.c index c9142554..24cfc1ef 100644 --- a/niftilib/nifti1_io.c +++ b/niftilib/nifti1_io.c @@ -4326,10 +4326,13 @@ nifti_image *nifti_image_read( const char *hname , int read_data ) #ifdef REJECT_COMPLEX if ((nim->datatype == DT_COMPLEX64) || (nim->datatype == DT_COMPLEX128) || (nim->datatype == DT_COMPLEX256)) { - fprintf(stderr,"Image Exception Unsupported datatype (COMPLEX64): use fslcomplex to manipulate: %s\n", hname); - exit(13); - } - #endif + fprintf(stderr,"Image Exception Unsupported datatype (COMPLEX): use fslcomplex to manipulate: %s\n", hname); + nifti_image_free(nim); + znzclose(fp); + free(hfile); + return NULL; + } + #endif if( g_opts.debug > 3 ){ fprintf(stderr,"+d nifti_image_read(), have nifti image:\n"); From 5c219c05ad38091c8bc099bd3ca02582630f0ce0 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 22 Sep 2026 08:43:08 -0500 Subject: [PATCH 2/2] ENH: Test that a complex image is rejected without ending the process Writes a DT_COMPLEX64 image and a DT_FLOAT32 image, then asserts nifti_image_read() returns NULL for the first and a usable image for the second, so a blanket refusal cannot pass. Registered only when FSLSTYLE_REJECT_COMPLEX is on. Against exit(13) the test process dies with status 13 before reaching either assertion. --- niftilib/CMakeLists.txt | 9 +++++ niftilib/nifti_reject_complex_test.c | 52 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 niftilib/nifti_reject_complex_test.c diff --git a/niftilib/CMakeLists.txt b/niftilib/CMakeLists.txt index 23461e87..db49b7bc 100644 --- a/niftilib/CMakeLists.txt +++ b/niftilib/CMakeLists.txt @@ -47,6 +47,15 @@ if(NIFTI_BUILD_TESTING AND NIFTI_BUILD_APPLICATIONS) COMMAND $ ) + if(FSLSTYLE_REJECT_COMPLEX) + add_executable(${NIFTI_PACKAGE_PREFIX}nifti_reject_complex_test nifti_reject_complex_test.c) + target_link_libraries(${NIFTI_PACKAGE_PREFIX}nifti_reject_complex_test ${NIFTI_NIFTILIB_NAME}) + add_test( + NAME nifti_reject_complex + COMMAND $ + ) + endif() + add_executable(nifti_second_test_program nifti_tester002.c) target_link_libraries(nifti_second_test_program ${NIFTI_PACKAGE_PREFIX}niftiio ) diff --git a/niftilib/nifti_reject_complex_test.c b/niftilib/nifti_reject_complex_test.c new file mode 100644 index 00000000..a0514b73 --- /dev/null +++ b/niftilib/nifti_reject_complex_test.c @@ -0,0 +1,52 @@ +/* With REJECT_COMPLEX, nifti_image_read() must report a complex image to + its caller and keep reading non-complex images. */ + +#include +#include +#include "nifti1_io.h" + +static int write_image(const char *fname, int datatype) +{ + int dims[8] = { 3, 4, 4, 4, 1, 1, 1, 1 }; + nifti_image *nim = nifti_make_new_nim(dims, datatype, 1); + if( nim == NULL ){ + fprintf(stderr, "FAILURE: could not create image for %s\n", fname); + return 1; + } + if( nifti_set_filenames(nim, fname, 0, 1) != 0 ){ + fprintf(stderr, "FAILURE: could not set filenames for %s\n", fname); + nifti_image_free(nim); + return 1; + } + nifti_image_write(nim); + nifti_image_free(nim); + return 0; +} + +int main(void) +{ + const char *cplx = "reject_complex_cplx.nii"; + const char *real = "reject_complex_real.nii"; + nifti_image *nim; + + if( write_image(cplx, DT_COMPLEX64) ) return 1; + if( write_image(real, DT_FLOAT32) ) return 1; + + nim = nifti_image_read(cplx, 1); + if( nim != NULL ){ + fprintf(stderr, "FAILURE: complex image was accepted\n"); + nifti_image_free(nim); + return 1; + } + + /* the rejection must be specific, not a blanket refusal */ + nim = nifti_image_read(real, 1); + if( nim == NULL ){ + fprintf(stderr, "FAILURE: non-complex image was rejected\n"); + return 1; + } + nifti_image_free(nim); + + printf("REJECT_COMPLEX test passed.\n"); + return 0; +}