Skip to content

Reorganize initialization and buffer allocation for gz* code#1928

Merged
Dead2 merged 3 commits intodevelopfrom
gzalloc
Aug 23, 2025
Merged

Reorganize initialization and buffer allocation for gz* code#1928
Dead2 merged 3 commits intodevelopfrom
gzalloc

Conversation

@Dead2
Copy link
Copy Markdown
Member

@Dead2 Dead2 commented Jul 4, 2025

  • Reorganize initialization and buffer allocation for gzopen/gzread/gzwrite
    Unify initialization code into gz_state_init() and gz_buffer_alloc().
  • Reintroduce a simplified version of @nmoinvaz's zng_alloc_aligned() function that was removed in 5b20867, and start using that for gz*
  • Use a single malloc call for both in and out buffers in gzopen/gzread/gzwrite.
  • Remove a malloc call from gzdopen().
  • Split out gz_read_init() from gzlook(), and rename gz_init() to gz_write_init().
    This makes gzread.c more like gzwrite.c, and fits in with the new code in gzlib.c.

In total, these changes should make the gz* code become a little easier to read and behave more like the rest of the zlib code.
This reduces the amount of malloc calls in gz* code from 7 places to 4.
The only malloc() calls I have not touched is the one in gz_open() that allocates state->path, and as far as I can tell there is no good way to define a good size for it, since the path can be short, or 32k long, or possibly even longer. And also the one that allocates state->msg ing in gz_error()

gz_state_init() initializes a few more state variables than either gzread or gzwrite code did previously, as an effect of unifying the code. gz_buffer_free() also makes sure to set pointers to NULL after freeing them, something the old code did not do.

Summary by CodeRabbit

  • Refactor

    • Centralized initialization, buffer lifecycle, and cleanup for gzip read/write, reducing duplicated setup/teardown.
  • New Features

    • Added aligned memory allocation for I/O buffers and explicit buffer management to improve alignment and performance.
  • Bug Fixes

    • Hardening of allocation/error paths and consolidated frees reduces memory-leak risk and makes open/read/write/close error handling more consistent.

@Dead2 Dead2 added the cleanup Improving maintainability or removing code. label Jul 4, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jul 4, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Warning

Rate limit exceeded

@Dead2 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 19 minutes and 47 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 92c2b86 and 63bb0b3.

📒 Files selected for processing (6)
  • gzguts.h (2 hunks)
  • gzlib.c (9 hunks)
  • gzread.c.in (4 hunks)
  • gzwrite.c (6 hunks)
  • zutil.c (1 hunks)
  • zutil.h (1 hunks)

Walkthrough

Adds aligned allocation helpers and centralizes gzFile state lifecycle and buffer management: introduces buffers in gz_state, new alloc/free helpers (gz_buffer_alloc, gz_buffer_free, gz_state_free), refactors init/cleanup across gz_open/gzdopen/gzread/gzwrite, and implements aligned alloc APIs in zutil.

Changes

Cohort / File(s) Change Summary
Core state & declarations
gzguts.h
Added unsigned char *buffers to gz_state; declared gz_buffer_alloc, gz_buffer_free, and gz_state_free.
State lifecycle & open/close
gzlib.c
Added gz_state_init and gz_state_free; added gz_buffer_alloc/gz_buffer_free; refactored gz_open/gzdopen to use centralized init/free and stack temp path; replaced scattered frees with gz_state_free.
Read path
gzread.c.in
Added gz_read_init to call gz_buffer_alloc and initialize inflate; replaced inline buffer/inflate setup with gz_read_init; use gz_buffer_free in close.
Write path
gzwrite.c
Renamed gz_initgz_write_init; replaced per-buffer allocations with gz_buffer_alloc/gz_buffer_free; simplified deflate init and consolidated state free to gz_state_free.
Aligned alloc impl
zutil.c
Added zng_alloc_aligned(unsigned size, unsigned align) and zng_free_aligned(void *ptr) implementing aligned allocation via zng_alloc/zng_free and bookkeeping.
Aligned alloc decl
zutil.h
Declared zng_alloc_aligned and zng_free_aligned.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant gzlib
  participant gz_state
  participant AlignedAlloc

  App->>gzlib: gz_open(...)
  gzlib->>gz_state: gz_state_init()
  gz_state->>AlignedAlloc: gz_buffer_alloc(state)
  AlignedAlloc-->>gz_state: state->buffers (aligned) set -> state->in/out assigned
  gz_state-->>gzlib: gzFile (initialized)
  App->>gzlib: gzread/gzwrite(...)
  gzlib->>gz_state: use state->in/out for stream ops
  App->>gzlib: gzclose()
  gzlib->>gz_state: gz_buffer_free(state)
  gzlib->>gz_state: gz_state_free(state)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • nmoinvaz
  • phprus
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gzalloc

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

🧹 Nitpick comments (1)
zutil.c (1)

113-149: Complex but correct aligned allocation implementation that could benefit from better documentation.

The aligned allocation logic is mathematically sound:

  • Correctly calculates alignment offset and ensures space for the original pointer
  • Properly stores and retrieves the original allocation address
  • Handles null pointers safely

However, the alignment calculation logic is complex and would benefit from more detailed comments explaining the algorithm, especially the case where align_diff < sizeof(void *).

Consider adding detailed comments explaining the alignment algorithm:

+/* Calculate return pointer address with space enough to store original pointer */
 align_diff = align - ((uintptr_t)ptr % align);
 return_ptr = (uintptr_t)ptr + align_diff;
+/* If there isn't enough space before the aligned address to store the original
+   pointer, advance to the next alignment boundary */
 if (align_diff < sizeof(void *))
     return_ptr += align;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 962ab42 and 4d0bbb9.

📒 Files selected for processing (6)
  • gzguts.h (2 hunks)
  • gzlib.c (9 hunks)
  • gzread.c.in (4 hunks)
  • gzwrite.c (6 hunks)
  • zutil.c (1 hunks)
  • zutil.h (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: mtl1979
PR: zlib-ng/zlib-ng#1925
File: arch/loongarch/lasxintrin_ext.h:38-65
Timestamp: 2025-07-04T16:59:44.683Z
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: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:14-24
Timestamp: 2025-02-21T01:41:50.358Z
Learning: In zlib-ng's SSE2 vectorized Chorba CRC implementation, the code that calls READ_NEXT macro ensures 16-byte alignment, making explicit alignment checks unnecessary within the macro.
Learnt from: samrussell
PR: zlib-ng/zlib-ng#1914
File: arch/generic/crc32_chorba_c.c:30-32
Timestamp: 2025-05-13T06:56:12.407Z
Learning: In zlib-ng, pointer casts between z_word_t* and uint64_t* are safe because: 1) On 64-bit platforms, z_word_t is defined as uint64_t, making the cast a no-op; 2) On 32-bit platforms where z_word_t is uint32_t, the code paths using uint64_t* are skipped in favor of 32-bit specific implementations.
Learnt from: samrussell
PR: zlib-ng/zlib-ng#1837
File: arch/generic/crc32_braid_c.c:215-217
Timestamp: 2024-12-27T10:06:16.184Z
Learning: There's a business requirement to use stack allocation instead of heap for the Chorba buffer.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1830
File: arch/generic/generic_functions.h:0-0
Timestamp: 2024-12-21T00:45:20.764Z
Learning: User Dead2 prefers English replies for code reviews, not Spanish.
zutil.h (5)
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: samrussell
PR: zlib-ng/zlib-ng#1914
File: arch/generic/crc32_chorba_c.c:30-32
Timestamp: 2025-05-13T06:56:12.407Z
Learning: In zlib-ng, pointer casts between z_word_t* and uint64_t* are safe because: 1) On 64-bit platforms, z_word_t is defined as uint64_t, making the cast a no-op; 2) On 32-bit platforms where z_word_t is uint32_t, the code paths using uint64_t* are skipped in favor of 32-bit specific implementations.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:14-24
Timestamp: 2025-02-21T01:41:50.358Z
Learning: In zlib-ng's SSE2 vectorized Chorba CRC implementation, the code that calls READ_NEXT macro ensures 16-byte alignment, making explicit alignment checks unnecessary within the macro.
Learnt from: mtl1979
PR: zlib-ng/zlib-ng#1925
File: arch/loongarch/lasxintrin_ext.h:38-65
Timestamp: 2025-07-04T16:59:44.683Z
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.
gzread.c.in (10)
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:81-83
Timestamp: 2024-10-08T19:37:14.998Z
Learning: When `INFLATE_STRICT` is not defined, the variable `state->dmax` is completely removed from the code.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-08T10:58:06.857Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-12T13:02:26.066Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:84-86
Timestamp: 2024-09-25T16:26:23.643Z
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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:127-130
Timestamp: 2024-10-08T19:37:14.998Z
Learning: In the `inflate_state` structure, fields like `lenbits`, `lencode`, `distcode`, and `distbits` may be moved within the structure for optimization purposes; they are not necessarily new additions.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:127-130
Timestamp: 2024-09-25T16:24:41.405Z
Learning: In the `inflate_state` structure, fields like `lenbits`, `lencode`, `distcode`, and `distbits` may be moved within the structure for optimization purposes; they are not necessarily new additions.
gzguts.h (8)
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:127-130
Timestamp: 2024-10-08T19:37:14.998Z
Learning: In the `inflate_state` structure, fields like `lenbits`, `lencode`, `distcode`, and `distbits` may be moved within the structure for optimization purposes; they are not necessarily new additions.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:127-130
Timestamp: 2024-09-25T16:24:41.405Z
Learning: In the `inflate_state` structure, fields like `lenbits`, `lencode`, `distcode`, and `distbits` may be moved within the structure for optimization purposes; they are not necessarily new additions.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:81-83
Timestamp: 2024-10-08T19:37:14.998Z
Learning: When `INFLATE_STRICT` is not defined, the variable `state->dmax` is completely removed from the code.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-08T10:58:06.857Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-12T13:02:26.066Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
zutil.c (11)
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: samrussell
PR: zlib-ng/zlib-ng#1914
File: arch/generic/crc32_chorba_c.c:30-32
Timestamp: 2025-05-13T06:56:12.407Z
Learning: In zlib-ng, pointer casts between z_word_t* and uint64_t* are safe because: 1) On 64-bit platforms, z_word_t is defined as uint64_t, making the cast a no-op; 2) On 32-bit platforms where z_word_t is uint32_t, the code paths using uint64_t* are skipped in favor of 32-bit specific implementations.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:14-24
Timestamp: 2025-02-21T01:41:50.358Z
Learning: In zlib-ng's SSE2 vectorized Chorba CRC implementation, the code that calls READ_NEXT macro ensures 16-byte alignment, making explicit alignment checks unnecessary within the macro.
Learnt from: mtl1979
PR: zlib-ng/zlib-ng#1925
File: arch/loongarch/lasxintrin_ext.h:38-65
Timestamp: 2025-07-04T16:59:44.683Z
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: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-23T16:49:52.043Z
Learning: In zlib-ng, bounds checking for CRC32 computation is handled by the caller, not within the individual CRC32 implementation functions like `crc32_chorba_sse2`.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:26-28
Timestamp: 2025-02-21T01:44:03.996Z
Learning: The alignment requirements for chorba_small_nondestructive_sse2 (16-byte alignment and multiple of 8 length) are enforced by its calling function, making additional checks redundant.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1802
File: arch/x86/chunkset_avx2.c:82-85
Timestamp: 2024-10-08T19:37:14.998Z
Learning: In `arch/x86/chunkset_avx2.c`, when working with AVX2-capable x86 CPUs, unaligned memory access using `_mm_loadu_si128` is acceptable since there is no performance penalty on architectures after Nehalem. Ensuring alignment may introduce unnecessary overhead due to arbitrary offsets into the window.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1802
File: arch/x86/chunkset_avx2.c:82-85
Timestamp: 2024-10-07T21:18:37.806Z
Learning: In `arch/x86/chunkset_avx2.c`, when working with AVX2-capable x86 CPUs, unaligned memory access using `_mm_loadu_si128` is acceptable since there is no performance penalty on architectures after Nehalem. Ensuring alignment may introduce unnecessary overhead due to arbitrary offsets into the window.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1830
File: arch/generic/generic_functions.h:39-53
Timestamp: 2024-12-20T23:35:59.830Z
Learning: The `longest_match_unaligned_*` functions are templated using the LONGEST_MATCH macro in match_tpl.h, so their implementations are generated rather than explicitly defined.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:830-831
Timestamp: 2025-02-21T01:37:54.508Z
Learning: The alignment calculation `((uintptr_t)16 - ((uintptr_t)buf & 15)) & 15` is safe from overflow as it's mathematically bounded between 1 and 16, making the use of uintptr_t appropriate for this pointer arithmetic.
gzwrite.c (8)
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-08T10:58:06.857Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-12T13:02:26.066Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:84-86
Timestamp: 2024-09-25T16:26:23.643Z
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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:81-83
Timestamp: 2024-10-08T19:37:14.998Z
Learning: When `INFLATE_STRICT` is not defined, the variable `state->dmax` is completely removed from the code.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
gzlib.c (10)
Learnt from: pps83
PR: zlib-ng/zlib-ng#0
File: :0-0
Timestamp: 2025-01-13T18:28:11.751Z
Learning: In zlib-ng, removing preprocessor guards (like HAVE_*) should be described as removing unused conditional compilation checks rather than removing functionality, as the underlying implementation often remains intact.
Learnt from: KungFuJesus
PR: zlib-ng/zlib-ng#1872
File: arch/x86/chorba_sse2.c:0-0
Timestamp: 2025-02-18T02:53:23.621Z
Learning: In zlib-ng, when macro names and parameters are self-explanatory and scalar versions of the code provide context, additional documentation for the macros may not be necessary.
Learnt from: samrussell
PR: zlib-ng/zlib-ng#1914
File: arch/generic/crc32_chorba_c.c:30-32
Timestamp: 2025-05-13T06:56:12.407Z
Learning: In zlib-ng, pointer casts between z_word_t* and uint64_t* are safe because: 1) On 64-bit platforms, z_word_t is defined as uint64_t, making the cast a no-op; 2) On 32-bit platforms where z_word_t is uint32_t, the code paths using uint64_t* are skipped in favor of 32-bit specific implementations.
Learnt from: mtl1979
PR: zlib-ng/zlib-ng#1925
File: arch/loongarch/lasxintrin_ext.h:38-65
Timestamp: 2025-07-04T16:59:44.683Z
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: Dead2
PR: zlib-ng/zlib-ng#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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:81-83
Timestamp: 2024-10-08T19:37:14.998Z
Learning: When `INFLATE_STRICT` is not defined, the variable `state->dmax` is completely removed from the code.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-08T10:58:06.857Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.h:108-108
Timestamp: 2024-10-12T13:02:26.066Z
Learning: The variable `state->was` in the `inflate_state` structure is used in the `inflateMark()` function in `inflate.c`.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#1797
File: inflate.c:84-86
Timestamp: 2024-09-25T16:26:23.643Z
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.
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
🧬 Code Graph Analysis (2)
zutil.c (3)
gzlib.c (4)
  • Z_INTERNAL (51-53)
  • Z_INTERNAL (72-99)
  • Z_INTERNAL (101-107)
  • Z_INTERNAL (559-586)
zutil.h (2)
  • size (136-136)
  • zng_free_aligned (137-137)
zutil_p.h (4)
  • zng_alloc (21-40)
  • zng_alloc (21-21)
  • zng_free (43-49)
  • zng_free (43-43)
gzlib.c (3)
zutil.c (4)
  • Z_INTERNAL (90-93)
  • Z_INTERNAL (103-106)
  • Z_INTERNAL (114-137)
  • Z_INTERNAL (139-149)
gzguts.h (4)
  • gz_state_free (141-141)
  • gz_buffer_alloc (139-139)
  • gz_buffer_free (140-140)
  • gz_error (138-138)
zutil.h (1)
  • zng_free_aligned (137-137)
🔇 Additional comments (19)
zutil.h (1)

136-137: LGTM! New aligned allocation functions are properly declared.

The function declarations follow the existing naming conventions and are appropriately marked as internal. These support the refactored buffer management in the gzip code.

gzread.c.in (4)

11-11: Good addition of initialization function declaration.

The new gz_read_init function declaration properly encapsulates read-specific initialization logic.


20-32: Well-structured initialization function with proper error handling.

The gz_read_init function consolidates buffer allocation and inflate initialization with appropriate cleanup on failure. The error handling correctly calls gz_buffer_free before returning failure.


99-101: Clean integration of centralized initialization.

Replacing the inline initialization logic with a call to gz_read_init improves code modularity and reduces duplication.


588-588: Consistent use of centralized buffer cleanup.

Replacing individual buffer free calls with gz_buffer_free aligns with the new buffer management pattern and ensures all related cleanup is handled consistently.

gzguts.h (2)

115-115: Good design improvement separating allocation from logical pointers.

Adding the buffers pointer to track the actual allocated memory separately from the logical in and out pointers is a clean design that supports aligned allocation while maintaining the existing interface.


139-141: Well-designed interface for centralized memory management.

The new function declarations provide a clean abstraction for buffer allocation, buffer cleanup, and state cleanup. This modularizes memory management across the gzip implementation.

gzwrite.c (8)

12-12: Good function renaming for clarity.

Renaming from gz_init to gz_write_init clearly indicates this function's purpose for write-specific initialization.


20-20: Function signature updated consistently.

The function definition correctly matches the new declaration.


24-26: Proper integration with centralized buffer allocation.

Using gz_buffer_alloc instead of direct memory allocation aligns with the new buffer management approach and provides consistent aligned allocation.


33-33: Consistent error handling with new buffer management.

Using gz_buffer_free on allocation failure ensures proper cleanup with the new buffer management system.


39-42: Appropriate simplification after centralizing buffer allocation.

Since gz_buffer_alloc now handles output buffer allocation, removing the explicit buffer setup here eliminates duplication while maintaining correct functionality.


48-48: All function calls updated consistently.

All references to the old gz_init function have been properly updated to gz_write_init.

Also applies to: 60-60, 158-158, 353-353


496-496: Consistent use of centralized buffer cleanup.

Using gz_buffer_free instead of individual buffer cleanup calls aligns with the new buffer management pattern.


502-502: Proper use of centralized state cleanup.

Using gz_state_free instead of direct zng_free ensures any additional state cleanup logic is properly executed.

gzlib.c (4)

26-49: Well-structured state initialization function.

The function properly encapsulates state allocation and initialization with appropriate default values and error handling.


101-107: Good defensive programming in buffer cleanup.

Setting pointers to NULL after freeing prevents use-after-free bugs.


125-126: Clean refactoring to use centralized state initialization.

Good use of the new gz_state_init() function for consistent state allocation and initialization.


289-295: Good optimization using stack allocation.

The change from dynamic to stack allocation is appropriate here since the buffer is only used temporarily within the function scope.

@codecov
Copy link
Copy Markdown

codecov bot commented Jul 4, 2025

Codecov Report

❌ Patch coverage is 70.83333% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.98%. Comparing base (ba3cc63) to head (63bb0b3).
⚠️ Report is 3 commits behind head on develop.

Files with missing lines Patch % Lines
gzlib.c 78.33% 9 Missing and 4 partials ⚠️
gzwrite.c 30.76% 5 Missing and 4 partials ⚠️
zutil.c 73.91% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1928      +/-   ##
===========================================
+ Coverage    81.47%   81.98%   +0.50%     
===========================================
  Files          162      162              
  Lines        13956    14013      +57     
  Branches      3120     3137      +17     
===========================================
+ Hits         11371    11488     +117     
+ Misses        1594     1557      -37     
+ Partials       991      968      -23     

☔ 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 requested a review from Copilot July 6, 2025 20:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors gzip file handling by centralizing state initialization and buffer management, introducing aligned memory allocation, and reducing the number of separate malloc calls in gz* code.

  • Unified gz state setup into gz_state_init() and teardown into gz_state_free().
  • Added zng_alloc_aligned()/zng_free_aligned() for aligned buffers and consolidated multiple allocations into a single call via gz_buffer_alloc().
  • Split and renamed read/write init routines (gz_read_init, gz_write_init) and cleaned up gzdopen() to remove an extra allocation.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
zutil.h Declared aligned allocation/free functions for internal use.
zutil.c Implemented zng_alloc_aligned() and zng_free_aligned().
gzwrite.c Renamed gz_initgz_write_init, replaced manual alloc/free with gz_buffer_*.
gzread.c.in Extracted gz_read_init() and switched to gz_buffer_alloc()/free.
gzlib.c Added gz_state_init/gz_state_free, gz_buffer_alloc/free, updated gz_open/gzdopen.
gzguts.h Added declarations for new buffer and state management routines.
Comments suppressed due to low confidence (3)

zutil.c:113

  • Add unit tests for zng_alloc_aligned and zng_free_aligned to verify correct alignment, allocation failure handling, and proper free behavior.
/* Provide aligned allocations, only used by gz* code */

gzlib.c:72

  • Consider adding integration tests for gz_buffer_alloc and gz_buffer_free under both read and write modes to ensure buffers are correctly sized, aligned, and cleaned up.
int Z_INTERNAL gz_buffer_alloc(gz_state *state) {

zutil.c:133

  • [nitpick] Ensure <string.h> (or the appropriate header) is included so that memcpy is properly declared, avoiding implicit declarations on some platforms.
    memcpy((void *)original_ptr, &ptr, sizeof(void *));

@mtl1979
Copy link
Copy Markdown
Collaborator

mtl1979 commented Jul 8, 2025

We might want to add tests that are supposed to fail so coverage gets better... Now the low patch coverage is completely caused by not testing with invalid parameter combinations.

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

♻️ Duplicate comments (1)
gzwrite.c (1)

158-159: Call sites assume gz_write_init() sets error on failure

Both gz_write() and gzvprintf() depend on gz_write_init() to set state->err when it fails. With the current implementation (see Lines 24-26), that may not happen on buffer allocation failure, leading to ambiguous 0/-1 returns with Z_OK. Once you apply the fix to set gz_error() on alloc failure, these paths will report errors correctly.

To confirm error propagation is correct across the codebase after your change, you can run:

#!/bin/bash
# Verify gz_buffer_alloc implementation and whether it sets gz_error/state->err.
# Also list all call sites to ensure no caller expects to set the error itself.

set -e

echo "== Locate gz_buffer_alloc definition with context =="
rg -n -C4 -g '!**/build/**' -P '^\s*(?:Z_INTERNAL\s+)?int\s+gz_buffer_alloc\s*\(\s*gz_state\s*\*\s*state\s*\)' || true

echo
echo "== Check for gz_error() within gz_buffer_alloc() implementation =="
rg -n -C2 -g '!**/build/**' -P 'gz_buffer_alloc\s*\(.*\)' -n | sed 's/:.*//' | sort -u | while read -r f; do
  echo "-- In $f --"
  rg -n -C2 -P 'gz_error\s*\(\s*state' "$f" || true
done

echo
echo "== Call sites of gz_write_init() and behavior on failure =="
rg -n -C3 -g '!**/build/**' -P '\bgz_write_init\s*\('

echo
echo "== Call sites of gz_buffer_alloc() (besides gz_write_init) =="
rg -n -C2 -g '!**/build/**' -P '\bgz_buffer_alloc\s*\('

Also applies to: 353-355

🧹 Nitpick comments (1)
gzwrite.c (1)

31-36: Differentiate deflateInit2() failures (not all are out-of-memory)

All non-OK returns from deflateInit2() are currently reported as Z_MEM_ERROR with "out of memory". That hides parameter/usage issues (Z_STREAM_ERROR) and version problems (Z_VERSION_ERROR), complicating debugging and tests that intentionally pass invalid parameters.

Proposed fix:

-        if (ret != Z_OK) {
-            gz_buffer_free(state);
-            gz_error(state, Z_MEM_ERROR, "out of memory");
-            return -1;
-        }
+        if (ret != Z_OK) {
+            gz_buffer_free(state);
+            int zerr = (ret == Z_MEM_ERROR) ? Z_MEM_ERROR :
+                       (ret == Z_VERSION_ERROR) ? Z_VERSION_ERROR :
+                       Z_STREAM_ERROR;
+            gz_error(state, zerr,
+                     (zerr == Z_MEM_ERROR) ? "out of memory" :
+                     (zerr == Z_VERSION_ERROR) ? "zlib version mismatch" :
+                     "deflateInit2() failed");
+            return -1;
+        }

This preserves meaningful error reporting for invalid parameter combinations and aligns with the comment asking for tests that intentionally fail.

Do you want me to add negative tests that validate these error paths (e.g., invalid level/strategy, invalid windowBits via open flags) to increase coverage as suggested by mtl1979?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5d5b0fe and 2550e51.

📒 Files selected for processing (6)
  • gzguts.h (2 hunks)
  • gzlib.c (9 hunks)
  • gzread.c.in (4 hunks)
  • gzwrite.c (6 hunks)
  • zutil.c (1 hunks)
  • zutil.h (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • zutil.h
  • gzguts.h
  • gzread.c.in
  • gzlib.c
  • zutil.c
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
📚 Learning: 2025-07-04T20:17:58.531Z
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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:

  • gzwrite.c
🧬 Code Graph Analysis (1)
gzwrite.c (1)
deflate.c (3)
  • PREFIX (709-781)
  • PREFIX (1190-1212)
  • deflateInit2 (283-419)
🔇 Additional comments (5)
gzwrite.c (5)

12-12: Rename and forward declaration look good

The gz_initgz_write_init rename and updated static prototype are consistent with the PR objective to mirror read/write sides. No issues spotted here.


39-43: Write buffer initialization is correct and consistent with new buffer API

Initializing avail_out/next_out from state->size/state->out and syncing state->x.next is correct. This assumes gz_buffer_alloc() allocated state->out when needed. Given the retrieved learning about intentional out == NULL when out_mult == 0 (direct mode), guarding init by if (!state->direct) is the right approach.


60-61: Lazy init via size==0 gate is sound

Deferring allocation until first use with state->size == 0 keeps behavior consistent and avoids redundant allocations. This also centralizes error handling to gz_write_init().


496-497: Centralized free: gz_buffer_free() is the right call

Replacing manual frees with gz_buffer_free(state) improves clarity and benefits from the PR’s behavior of NULL-ing pointers to prevent accidental reuse.


503-503: Final state cleanup aligned with new lifecycle API

Using gz_state_free(state) instead of raw zng_free is consistent with the centralized lifecycle management introduced in gzlib.c. Good move.

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

🔭 Outside diff range comments (1)
gzwrite.c (1)

128-146: Fix potential infinite loop in gz_zero() when uninitialized

If gz_zero() is entered before any init and strm->avail_in == 0, state->size is 0, n becomes 0, and len never changes, resulting in an infinite loop. Ensure initialization before using state->size/state->in.

Apply this diff:

 static int gz_zero(gz_state *state, z_off64_t len) {
     int first;
     unsigned n;
     PREFIX3(stream) *strm = &(state->strm);

+    /* allocate memory if this is the first time through */
+    if (state->size == 0 && gz_write_init(state) == -1)
+        return -1;
+
     /* consume whatever's left in the input buffer */
     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
         return -1;
♻️ Duplicate comments (1)
gzwrite.c (1)

24-28: Good: gz_error is now set on gz_buffer_alloc() failure (resolves prior gap)

This fixes the diagnostics hole noted earlier—callers will now see Z_MEM_ERROR via gzerror().

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2550e51 and 92c2b86.

📒 Files selected for processing (2)
  • gzread.c.in (4 hunks)
  • gzwrite.c (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • gzread.c.in
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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.
📚 Learning: 2025-07-04T20:17:58.531Z
Learnt from: Dead2
PR: zlib-ng/zlib-ng#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:

  • gzwrite.c
🧬 Code Graph Analysis (1)
gzwrite.c (1)
deflate.c (3)
  • PREFIX (709-781)
  • PREFIX (1190-1212)
  • deflateInit2 (283-419)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
  • GitHub Check: Windows MSVC 2022 v140 Win64
🔇 Additional comments (7)
gzwrite.c (7)

12-12: Rename to gz_write_init is clear and consistent

Renaming the internal initializer to gz_write_init brings symmetry with gz_read_init and improves clarity.


41-45: Intentional: no out buffer in direct mode is OK

Initializing only the write buffer for the compressed path and leaving state->out NULL in direct mode is correct (gz_buffer_alloc intentionally leaves out NULL when out_mult == 0). This aligns with the retrieved learning.


61-64: LGTM: first-time init guard in gz_comp

The state->size gate with gz_write_init() is correct and keeps lazy allocation semantics intact.


159-162: LGTM: first-time init guard in gz_write

Consistent with gz_comp/gzvprintf; correct return semantics on init failure.


355-356: LGTM: gzvprintf returns state->err on init failure

Returning state->err preserves the established API behavior and surfaces the underlying cause.


499-505: Ownership boundaries confirmed – no double‐free risk
gz_buffer_free() only frees the aligned buffers (via zng_free_aligned) and resets state->in, state->out, and state->size. free(state->path) handles the path. gz_state_free() simply calls zng_free(state), freeing only the gz_state struct itself. There’s no overlap or double‐free between these calls.


35-35: Confirmed: gz_buffer_free() resets state->size to 0, preserving init guards

Reviewing gzlib.c shows that gz_buffer_free (nulls state->buffers, state->out, state->in) also sets
• state->size = 0 (at gzlib.c:106)

No further changes are needed.

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.

Change looks good. As long as gz operations never need to reallocate either of the buffer sizes after initializing. Probably also provides cpu caching stuff since buffers are sequential in memory. I reviewed each commit separately so ignore any comments that don't apply to the final product.

Dead2 added 2 commits August 20, 2025 16:32
in and outbuffers in gzopen/gzread/gzwrite.
Also start aligning the allocation to 64 bytes (on a cacheline border).
…ite_init().

This makes gzread.c more like gzwrite.c, and fits in with the new code in gzlib.c.
@Dead2
Copy link
Copy Markdown
Member Author

Dead2 commented Aug 20, 2025

Rebased and applied fixes for feedback

@Dead2 Dead2 merged commit 4c6ec4c into develop Aug 23, 2025
366 of 376 checks passed
@Dead2 Dead2 deleted the gzalloc branch November 29, 2025 22:48
@coderabbitai coderabbitai bot mentioned this pull request Apr 11, 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants