Skip to content

BUG: Validate the GIPL header byte count in a single read - #6628

Merged
hjmjohnson merged 1 commit into
InsightSoftwareConsortium:mainfrom
physwkim:bug-gipl-io-header-6575
Jul 14, 2026
Merged

hjmjohnson merged 1 commit into
InsightSoftwareConsortium:mainfrom
physwkim:bug-gipl-io-header-6575

Conversation

@physwkim

Copy link
Copy Markdown
Contributor

GiplImageIO consumed the 256-byte header as 17 separate gzread/istream::read calls without ever checking a byte count, so a truncated or non-GIPL file populated dimensions, spacing and origin from uninitialized stack memory. Addresses B86 of #6575.

Root cause and fix

Once one read on a broken stream fails, every later read silently no-ops. float pixdim[4] and double origin[4] are never zero-initialized, so their indeterminate values went straight into m_Spacing/m_Origin — undefined behavior, not merely wrong metadata.

The fix is structural rather than 17 guards: ReadImageInformation() now reads the whole 256-byte header in one call, checks the byte count once, and memcpys the four field groups it actually uses out of that buffer at their documented offsets. The ten other fields the old code read were never assigned to any member and existed only to advance the cursor, which the one-shot read now does; the trailing magic_number re-read was likewise never compared against anything (CanReadFile() does the magic-number check, in its own function). CanReadFile()'s own two reads now check their byte count and return false on a short read.

Local validation

Two cases added to itkGiplImageIOGTest.cxx, calling ReadImageInformation() directly on a bare GiplImageIO — going through ImageFileReader::Update() masks the bug, because the already-fixed pixel-data check throws first once it inherits the broken stream.

  • ReadImageInformationOfHeaderTruncatedUncompressedFileThrows / ...CompressedFileThrows — fail-before: throws nothing. Pass-after: throws.

ctest -R Gipl: no existing test's result changed.

AI assistance

ReadImageInformation consumed the 256-byte header as 15 unchecked
gzread/istream::read calls, and CanReadFile did 2 more; a truncated
or non-GIPL file silently left pixdim/origin locals uninitialized
and populated spacing and origin from stack garbage instead of
failing.

Read the header in one call and check the byte count once, then
parse dims/image_type/pixdim/origin from that buffer. The other
fields (line1, matrix, flags, min/max, pixval, user_def,
magic_number) were dead: unread by any member, and magic_number
was never compared; only CanReadFile validates it. CanReadFile's
own probe now checks its read count instead of trusting zero-init.

Addresses item B86 of InsightSoftwareConsortium#6575.
@github-actions github-actions Bot added type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:IO Issues affecting the IO module labels Jul 14, 2026
@greptile-apps

greptile-apps Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens GIPL header parsing for truncated files. The main changes are:

  • Single 256-byte header read in ReadImageInformation().
  • Byte-count checks for plain and compressed GIPL headers.
  • Field extraction from fixed header offsets.
  • Tests for truncated compressed and uncompressed headers.

Confidence Score: 5/5

This looks safe to merge.

No blocking issues found in the changed code.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the GIPL header truncation validation harness and captured a transcript showing the commands run, working directory, and exit codes.
  • Saved the GIPL header truncation harness source file gipl_header_truncation_harness.cxx for review.
  • Confirmed the harness reported that both the uncompressed 100-byte header and the compressed 20-byte header were truncated with the message 'GIPL header is truncated...', and the executable exited with code 0.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
Modules/IO/GIPL/src/itkGiplImageIO.cxx Reads the fixed GIPL header in one checked operation and keeps the consumed stream position aligned with later pixel reads.
Modules/IO/GIPL/test/itkGiplImageIOGTest.cxx Adds tests that call ReadImageInformation() directly on truncated plain and compressed GIPL files.

Reviews (2): Last reviewed commit: "BUG: Validate GIPL header byte count in ..." | Re-trigger Greptile

@hjmjohnson
hjmjohnson marked this pull request as draft July 14, 2026 14:58
@hjmjohnson
hjmjohnson marked this pull request as ready for review July 14, 2026 20:04
@hjmjohnson
hjmjohnson merged commit e357b46 into InsightSoftwareConsortium:main Jul 14, 2026
19 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:IO Issues affecting the IO module type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants