Skip to content

BUG: Fix signed/unsigned comparisons in the nifti tools - #51

Merged
hjmjohnson merged 1 commit into
InsightSoftwareConsortium:masterfrom
gdevenyi:pr/fix-sign-compare
Sep 22, 2026
Merged

hjmjohnson merged 1 commit into
InsightSoftwareConsortium:masterfrom
gdevenyi:pr/fix-sign-compare

Conversation

@gdevenyi

@gdevenyi gdevenyi commented Aug 15, 2026 •

Copy link
Copy Markdown

Three -Wsign-compare warnings, each comparing a signed value against an
unsigned one, where the signed operand is silently converted and a
negative value would compare as enormous.

nifti1_tool.c, nifti_tool.c, fill_cmd_string()
len < 0 || len >= remain, len an int, remain a size_t. The
len < 0 test short-circuits first, so the conversion could not
actually misfire, but the comparison relies on that ordering to be
correct. Made explicit, matching the idiom used a few lines above.

nifti_tool.c, read_file_text()
bytes != len64, size_t against int64_t. len64 is validated as
> 0 and <= INT_MAX immediately above, so the cast is lossless.


Interface impact: none. On the union of all these changes, configured with USE_FSL_CODE=ON and USE_CIFTI_CODE=ON: all 448 exported symbols across libniftiio, libnifti2, libznz, libfslio, libnifticdf and libcifti are identical to master under nm -D --defined-only, and all ten installed headers are identical under gcc -E -P. Under gcc -dM -E one macro definition differs, intentionally and only in text: #61 makes FSL_RADIOLOGICAL read (-1) so it is safe inside an expression. Its value is still -1, checked by compiling against each installed fslio.h and printing it.

Verification. This branch: builds with gcc 16.1.1, ctest unchanged from master (2 of 345 fail on master itself in this environment; #31 and #29 each fix one). The union of all the PRs: 0 errors under both gcc 16.1.1 and clang 22.1.8, ctest 345/345 under each, and the whole suite under valgrind memcheck with --trace-children=yes gives 484 traced processes with no invalid access, no uninitialised value and no leak in any nifti binary.

Coordination. Every line of every branch was compared, whitespace-normalised, against the diffs of the open PRs (#11, #21, #22, #23, #24). Where one of those already changes a line, the line was left alone, and the few deliberate overlaps are named in the text above. What survives is 17 compiler warnings, all of them on those lines: 9 -Wsign-conversion (5 in fslio.c for #22, 2 in nifti2_io.c and 2 in nifti_tester001.c for #24) and 8 -Wcalloc-transposed-args in nifti_findhdrname and nifti_findimgname, which #11 rewrites. No formatting changes appear anywhere, to stay clear of #10 and #12.

One of a set of independent, single-purpose PRs. Each bases on master and can be merged on its own, in any order.

The full set of PRs (35)

The union of all of them is on the fork as all-changes, if you want to build and test the lot at once.

CI and build

Configuration and documentation

Defects

Warning and check classes

This was referenced Aug 15, 2026
Three -Wsign-compare warnings, each comparing a signed value against an
unsigned one, where the signed operand is silently converted and a
negative value would compare as enormous.

  nifti1_tool.c, nifti_tool.c, fill_cmd_string()
      `len < 0 || len >= remain`, len an int, remain a size_t.  The
      `len < 0` test short-circuits first, so the conversion could not
      actually misfire, but the comparison relies on that ordering to be
      correct.  Made explicit, matching the idiom used a few lines above.

  nifti_tool.c, read_file_text()
      `bytes != len64`, size_t against int64_t.  len64 is validated as
      > 0 and <= INT_MAX immediately above, so the cast is lossless.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSPnbwpDjVcAYqDdVqLkMU
@hjmjohnson

Copy link
Copy Markdown
Member

Rebased onto current master. These three lines are what currently fails two CI jobs.

coverage-gcc-linux and valgrind-gcc-linux both report 0 Compiler errors, 2 Compiler warnings and then fail at cmake/nifti_common.cmake:472, which treats any warning as fatal. Reproduced with the coverage job's own flags on Ubuntu 24.04 / GCC 13.3, the warnings are exactly the lines this PR changes:

nifti2/nifti_tool.c:888    comparison of integer expressions of different signedness [-Wsign-compare]
nifti2/nifti_tool.c:2370   comparison of integer expressions of different signedness [-Wsign-compare]
niftilib/nifti1_tool.c:726 comparison of integer expressions of different signedness [-Wsign-compare]

With this branch, the same build gives 0 warnings and 345/345 tests passing.

The casts are value-preserving

Each comparison is between a snprintf or fread result and a size_t bound.

len is int and is already tested for len < 0 on the same line before the cast is reached, so (size_t)len only ever converts a non-negative value. bytes is size_t and len64 is int64_t holding a file length that the surrounding code has already established is positive.

No input changes behaviour; the casts make the conversion the compiler was performing implicitly visible at the call site.

What this unblocks
Job Blocker Fixed by
use_prefix-gcc-linux — already green
sanitize-clang-linux scan-build: command not found, exit 127 #78
rel-clang-macos brew install sed fails, exit 1 #78
coverage-gcc-linux these two warnings this PR
valgrind-gcc-linux these two warnings this PR

Together with #78 this takes all five Build and Test jobs green. The gate at nifti_common.cmake:472 is doing what it was written to do and does not need changing.

@hjmjohnson
hjmjohnson merged commit e039528 into InsightSoftwareConsortium:master Sep 22, 2026
19 of 21 checks passed
@hjmjohnson

Copy link
Copy Markdown
Member

The commit messages in this range were rewritten to remove trailers that do not belong in permanent history: Co-Authored-By: naming an AI tool, and Claude-Session: URLs that resolve for nobody. Only messages changed — the tree at the tip of master is byte-identical, and author, committer, and dates are preserved.

This PR's commit on the rewritten master:

  • 7b37e32117 BUG: Fix signed/unsigned comparisons in the nifti tools

The SHA recorded above by GitHub is from the pre-rewrite history and no longer resolves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants