From 7d0bd08bfe49f006edd558563df31ce42eb7edfc Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Sat, 15 Aug 2026 16:41:33 -0400 Subject: [PATCH] BUG: Check dim[0] before using it to index dim[] in the NIFTI-2 converter nifti_convert_n2hdr2nim() uses nhdr.dim[0], the number of dimensions, as a loop bound over the eight-element dim[] array: for( ii=2 ; ii <= nhdr.dim[0] ; ii++ ) ... for( ii=nhdr.dim[0]+1 ; ii <= 7 ; ii++ ) ... for( ii=1 ; ii <= nhdr.dim[0] ; ii++ ) ... It never checks that dim[0] is in [0,7]. The NIFTI-1 converter gets that check for free, because need_nhdr_swap() rejects a dim[0] outside [1,7] in either byte order, but the NIFTI-2 path decides swapping from sizeof_hdr and reaches the loops with whatever the file said. A NIFTI-2 header with a large negative dim[0] therefore starts the second loop at a wild negative index, reads far outside the header and segfaults. This is not confined to the header API: nifti_image_read() gets there for any file with a valid 540 byte NIFTI-2 header, so a 604 byte file crashes nifti_tool: $ nifti_tool -disp_nim -infiles bad_n2_dim0.nii nifti2_io.c:5079: runtime error: index -6727636073941130588 out of bounds for type 'int64_t[8]' AddressSanitizer: SEGV ... in nifti_convert_n2hdr2nim dim[0] is now range checked in the same place, and in the same style, as the dim[1] check just below it. Zero stays acceptable, as it is on the NIFTI-1 side. Valid headers are unaffected: dim[0] outside [0,7] has no meaning in either format. Found by fuzzing nifti_convert_n2hdr2nim() with clang's libFuzzer under AddressSanitizer. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014m231RPDZPDbYDVxawxpjG --- nifti2/nifti2_io.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nifti2/nifti2_io.c b/nifti2/nifti2_io.c index 43a26f71..566005c7 100644 --- a/nifti2/nifti2_io.c +++ b/nifti2/nifti2_io.c @@ -5036,6 +5036,14 @@ nifti_image* nifti_convert_n2hdr2nim(nifti_2_header nhdr, const char * fname) ERREX("bad datatype") ; } + /* dim[0] is the number of dimensions and the loops below index dim[] + with it; the NIFTI-1 path gets this check from need_nhdr_swap() */ + if( nhdr.dim[0] < 0 || nhdr.dim[0] > 7 ) + { + free(nim); + ERREX("bad dim[0]") ; + } + if( nhdr.dim[1] <= 0 ) { free(nim);