Skip to content

Update static analyzer to GCC-14, fix infinite loop warning, add Z_UNREACHABLE#2101

Merged
Dead2 merged 3 commits intodevelopfrom
gzread-infinite-loop
Jan 14, 2026
Merged

Update static analyzer to GCC-14, fix infinite loop warning, add Z_UNREACHABLE#2101
Dead2 merged 3 commits intodevelopfrom
gzread-infinite-loop

Conversation

@Dead2
Copy link
Copy Markdown
Member

@Dead2 Dead2 commented Jan 13, 2026

Updating to the newer static analyzer in GCC-14 from GCC-10 revealed a possible infinite loop in gz_fetch(), it doesn't happen, but the compiler/analyzer can't know that.
Ref: https://github.com/zlib-ng/zlib-ng/actions/runs/20957066511/job/60224228645?pr=2096

  • Update static analyzer to GCC-14
  • Add default case that returns error in gz_fetch()
  • According to the comment, gz_fetch() also assumes that state->x.have == 0, so lets add an Assert to that effect.
  • Add Z_UNREACHABLE hint and use it for unreachable default cases.

@Dead2 Dead2 added cleanup Improving maintainability or removing code. Continuous Integration Warnings fix labels Jan 13, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Jan 13, 2026

Codecov Report

❌ Patch coverage is 40.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.43%. Comparing base (83a14aa) to head (fd80f60).
⚠️ Report is 11 commits behind head on develop.

Files with missing lines Patch % Lines
gzread.c 50.00% 2 Missing ⚠️
deflate.c 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2101      +/-   ##
===========================================
+ Coverage    83.93%   84.43%   +0.50%     
===========================================
  Files          156      158       +2     
  Lines        13184    13557     +373     
  Branches      3211     3378     +167     
===========================================
+ Hits         11066    11447     +381     
- Misses        1061     1063       +2     
+ Partials      1057     1047      -10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Dead2 Dead2 changed the title Update static analyzer to GCC-14, fix Update static analyzer to GCC-14, fix possible infinite loop, add Z_UNREACHABLE Jan 13, 2026
…c analyzer.

According to the comment, gz_fetch() also assumes that state->x.have == 0, so
lets add an Assert to that effect.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 13, 2026

Walkthrough

Renames CI GCC job and updates Ubuntu toolchain and CC to gcc-14. Adds public macro Z_UNREACHABLE() in zbuild.h and uses it in deflate.c and gzread.c; also adds an assertion and a loop continue in gz_fetch to tighten control flow.

Changes

Cohort / File(s) Summary
CI / Build System
.github/workflows/analyze.yml
Renamed job from GCC to GCC-14; updated Ubuntu toolchain installation and CC env to use gcc-14 (replacing gcc-10).
Macro Definition
zbuild.h
Adds public macro Z_UNREACHABLE() with conditional definitions: C23 unreachable(), GCC/Clang __builtin_unreachable(), or no-op fallback; guarded by #ifndef Z_UNREACHABLE.
Runtime checks / control flow
deflate.c, gzread.c
Inserted Z_UNREACHABLE() in switch default/unreachable paths; in gz_fetch added an entry assertion (state->x.have == 0) and a continue after successful GZIP decompression to enforce expected flow.

Suggested labels

Build Env

Suggested reviewers

  • nmoinvaz
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the context, root cause (GCC-14 analyzer warning), and all changes made, directly matching the changeset modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately summarizes all three main changes: updating GCC to version 14, fixing the infinite loop warning, and introducing the Z_UNREACHABLE macro.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gzread-infinite-loop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Dead2 Dead2 force-pushed the gzread-infinite-loop branch from 6fe0e32 to c0b579f Compare January 13, 2026 15:25
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
gzread.c (1)

228-237: LGTM! The continue is essential to prevent fallthrough.

The continue on line 233 is necessary to prevent the GZIP case from falling through into the new default case. Without it, successful decompression would incorrectly trigger Z_UNREACHABLE() and return -1.

Minor style note: line 234 uses a C++ style comment (//) while the rest of the file uses C-style comments (/* */). This works in C99+ but is inconsistent with the file's style.

Optional: Use C-style comment for consistency
-        default:    // Can't happen
+        default:    /* Can't happen */
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe0e32 and c0b579f.

📒 Files selected for processing (3)
  • deflate.c
  • gzread.c
  • zbuild.h
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: mtl1979
Repo: zlib-ng/zlib-ng PR: 1925
File: arch/loongarch/lasxintrin_ext.h:38-65
Timestamp: 2025-07-04T16:59:44.725Z
Learning: In zlib-ng, the policy for supporting old compilers is to maintain compatibility for up to two years after GitHub removes support for them in CI, or when there is no long-time contributor left testing for the architecture if the architecture was not supported by GitHub Actions at all.
Learnt from: nmoinvaz
Repo: zlib-ng/zlib-ng PR: 2077
File: crc32.c:34-45
Timestamp: 2026-01-12T22:53:18.025Z
Learning: In zlib-ng, defensive NULL checks at public API entry points (like crc32() checking buf before calling crc32_z()) are intentional and should not be flagged as redundant, even when the called function also checks. This is an accepted defensive coding practice.
📚 Learning: 2026-01-12T22:53:18.025Z
Learnt from: nmoinvaz
Repo: zlib-ng/zlib-ng PR: 2077
File: crc32.c:34-45
Timestamp: 2026-01-12T22:53:18.025Z
Learning: Treat defensive NULL checks at public API entry points (e.g., crc32() checking buf before calling crc32_z()) as intentional and not redundant. This pattern applies across C files in the zlib-ng repository wherever public APIs perform boundary validation before delegating to internal logic.

Applied to files:

  • deflate.c
  • gzread.c
📚 Learning: 2024-10-08T19:37:14.998Z
Learnt from: Dead2
Repo: zlib-ng/zlib-ng PR: 1797
File: inflate.c:84-86
Timestamp: 2024-10-08T19:37:14.998Z
Learning: When `INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR` is not defined, `state->sane` is completely removed from the codebase and does not need to be initialized.

Applied to files:

  • deflate.c
📚 Learning: 2025-08-20T14:34:15.867Z
Learnt from: Dead2
Repo: zlib-ng/zlib-ng PR: 1928
File: gzwrite.c:0-0
Timestamp: 2025-08-20T14:34:15.867Z
Learning: Z_VERSION_ERROR is used by zlib but not by zlib-ng, so it should not be included in error handling for zlib-ng deflateInit2() calls.

Applied to files:

  • deflate.c
📚 Learning: 2025-12-08T13:43:07.260Z
Learnt from: Dead2
Repo: zlib-ng/zlib-ng PR: 2046
File: deflate_quick.c:116-116
Timestamp: 2025-12-08T13:43:07.260Z
Learning: In zlib-ng, the compare256() function (called through the function table) returns at most 256, so match_len calculations of the form `compare256(...) + 2` are inherently bounded to a maximum of 258 (which equals STD_MAX_MATCH), making explicit clamping to STD_MAX_MATCH unnecessary after such calculations.

Applied to files:

  • deflate.c
📚 Learning: 2025-10-12T17:01:13.630Z
Learnt from: mtl1979
Repo: zlib-ng/zlib-ng PR: 1980
File: compress.c:31-33
Timestamp: 2025-10-12T17:01:13.630Z
Learning: In zlib-ng, when ZLIB_COMPAT is defined, z_int32_t is typedef'd as `int` (not int32_t), and zlib.h is included (which uses `int` in function signatures). This allows the implementation to use z_int32_t while maintaining backwards compatibility with the original zlib API that uses `int`. When ZLIB_COMPAT is not defined, z_int32_t is typedef'd as int32_t and zlib-ng.h is used instead.

Applied to files:

  • deflate.c
📚 Learning: 2026-01-12T02:33:10.554Z
Learnt from: mtl1979
Repo: zlib-ng/zlib-ng PR: 2097
File: zlib.map.in:20-24
Timestamp: 2026-01-12T02:33:10.554Z
Learning: The zlib.map.in file should remain as close as possible to Mark Adler's version of zlib. Changes that would improve readability or consistency (such as adding explicit `global:` keywords) should not be made unless they are first adopted in the upstream zlib project.

Applied to files:

  • gzread.c
📚 Learning: 2025-07-04T20:17:58.531Z
Learnt from: Dead2
Repo: zlib-ng/zlib-ng PR: 1928
File: gzlib.c:90-90
Timestamp: 2025-07-04T20:17:58.531Z
Learning: In zlib-ng's gz_buffer_alloc() function, the condition `(out_mult >= 1 && state->out == NULL)` is necessary because state->out is intentionally left as NULL when out_mult == 0 (write + direct mode), but should be allocated when out_mult >= 1. The condition properly distinguishes between intentionally NULL buffers and allocation failures.

Applied to files:

  • gzread.c
📚 Learning: 2026-01-12T23:00:52.569Z
Learnt from: nmoinvaz
Repo: zlib-ng/zlib-ng PR: 2077
File: test/test_crc32_copy.cc:15-29
Timestamp: 2026-01-12T23:00:52.569Z
Learning: In zlib-ng PR #2077, the test data in hash_test_strings_p.h (hash_tests array) was structured to exclude NULL buffer cases. NULL handling is performed at the API level in adler32.c and crc32.c, so test implementations in test_crc32_copy.cc and test_adler32_copy.cc do not need NULL guards for memcmp calls.

Applied to files:

  • gzread.c
📚 Learning: 2024-09-25T16:25:56.686Z
Learnt from: Dead2
Repo: zlib-ng/zlib-ng PR: 1797
File: inflate.c:81-83
Timestamp: 2024-09-25T16:25:56.686Z
Learning: When `INFLATE_STRICT` is not defined, the variable `state->dmax` is completely removed from the code.

Applied to files:

  • gzread.c
🔇 Additional comments (2)
deflate.c (1)

713-716: LGTM!

The Z_UNREACHABLE() placement is correct. The default case is genuinely unreachable since s->wrap is validated and constrained to 0, 1, or 2 (when GZIP is defined) during initialization. The fallback assignment after Z_UNREACHABLE() is necessary since the macro may be a no-op on some compilers.

gzread.c (1)

212-212: LGTM!

The assertion correctly enforces the function's precondition documented in the comment on line 204: "Assumes state->x.have is 0."

@Dead2 Dead2 force-pushed the gzread-infinite-loop branch from c0b579f to fd80f60 Compare January 13, 2026 17:55
Copy link
Copy Markdown
Member

@nmoinvaz nmoinvaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok to me.

@Dead2 Dead2 changed the title Update static analyzer to GCC-14, fix possible infinite loop, add Z_UNREACHABLE Update static analyzer to GCC-14, fix infinite loop warning, add Z_UNREACHABLE Jan 13, 2026
@Dead2 Dead2 merged commit e5129cf into develop Jan 14, 2026
317 of 322 checks passed
@Dead2 Dead2 mentioned this pull request Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cleanup Improving maintainability or removing code. Continuous Integration Warnings fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants