Skip to content

inflate: annotate sliding window with sized_by_or_null - #1313

Open
LaptopsPlural wants to merge 1 commit into
madler:developfrom
LaptopsPlural:local/window-fbounds-safety
Open

LaptopsPlural wants to merge 1 commit into
madler:developfrom
LaptopsPlural:local/window-fbounds-safety

Conversation

@LaptopsPlural

@LaptopsPlural LaptopsPlural commented Sep 11, 2026

Copy link
Copy Markdown

Summary

Annotate private inflate_state.window with a native __attribute__((__sized_by_or_null__(wsize))) (or __counted_by_or_null__ fallback) behind __has_attribute, and keep capacity-before-pointer updates in inflate.c so the window↔wsize relationship stays consistent for static checking.

Default builds are unchanged: unsupported compilers see an ordinary pointer; no new headers, configure options, or CMake toggles.

Test plan

  • Default ./configure && make && make check

@Vollstrecker

Copy link
Copy Markdown
Contributor

I'm not sure why to add his as a header, but if this is really important for safety and it works, why is it an option? And why can this be enabled when clang is not used? And why did you change cmake wen your estplan is just configure?

Not to mention why this is a benefit/problem.

@LaptopsPlural

Copy link
Copy Markdown
Author

Thanks for the questions — happy to clarify.

Why a header?
zlib_bounds_safety.h is a small private helper (included from inflate.h, not from public zlib.h) that centralizes the ZLIB_SIZED_BY* / ZLIB_COUNTED_BY* macros. The idea is to keep the annotation plumbing in one place and out of the public API surface. inflate.h already documents that it is internal and subject to change; applications should only use zlib.h. Putting the macros in a dedicated header also makes it easier to reuse the same inert-by-default pattern later if maintainers want annotations on other internal buffer/capacity pairs.

Why optional if it matters for safety?
-fbounds-safety is still experimental and not available in every toolchain (and not in typical gcc builds). The macros are empty unless ZLIB_SUPPORT_FBOUNDS_SAFETY is defined, so default builds stay unchanged: same layout, same ABI, no new flags, no reliance on Clang. Making it opt-in avoids forcing an experimental compiler feature on everyone while still letting a bounds-safety-capable Clang enforce the window/wsize relationship when maintainers choose to enable it.

Why can this be “enabled” when Clang is not used?
With the option off (the default), any compiler is fine — the macros expand to nothing. With the option on, the build defines ZLIB_SUPPORT_FBOUNDS_SAFETY and passes -fbounds-safety, and the header #includes <ptrcheck.h>. That path is only intended for a Clang that actually implements those annotations; on a non-supporting toolchain it should fail at compile time rather than silently change behavior. There is currently no hard “must be Clang” guard in CMake/Makefile.in. If you would prefer that (refuse the option unless the compiler supports -fbounds-safety), I am happy to add that check or tighten the wiring.

Why change CMake when the test plan is just configure?
Fair point. Makefile.in got ENABLE_FBOUNDS_SAFETY for the classic ./configure && make path; CMake got ZLIB_ENABLE_FBOUNDS_SAFETY only for parity with people who build via CMake. The test plan I listed focused on configure because that is what I verified locally. If the CMake bits are unnecessary for this PR’s scope, I am glad to drop the CMakeLists.txt changes and keep only the configure/Make path (or the reverse, if you prefer one build system only).

What benefit / problem does this address?
This does not claim a known CVE. Inflate already tracks an allocated sliding window (window) and its capacity (wsize). The annotation ties that pointer to its companion capacity with ZLIB_SIZED_BY_OR_NULL(wsize) so that, when built with a bounds-safety-capable Clang, the compiler can check spatial safety on uses of that buffer. Related hygiene in inflate.c / infback.c keeps capacity and pointer updates consistent with that invariant (e.g. capacity-before-pointer on allocate; keep wsize across reset when the allocation is retained; null-then-zero on free). Default gcc/configure builds remain inert and behaviorally the same.

Happy to revise along whatever direction you and the maintainers prefer — especially dropping CMake and/or gating the option more strictly.

Tie inflate_state.window to its capacity (wsize) with a native
__attribute__((__sized_by_or_null__(wsize))) (or counted_by_or_null
fallback) guarded by __has_attribute so unsupported compilers see an
ordinary pointer. Keep capacity-before-pointer updates in inflate.c so
the relationship stays consistent across allocate, reset, and free.

Default builds are unchanged: no new headers, configure options, or
CMake toggles.
@LaptopsPlural
LaptopsPlural force-pushed the local/window-fbounds-safety branch from 3144388 to e753135 Compare September 13, 2026 01:22
@LaptopsPlural LaptopsPlural changed the title inflate: add optional -fbounds-safety annotation for sliding window inflate: annotate sliding window with sized_by_or_null Sep 13, 2026
@LaptopsPlural

Copy link
Copy Markdown
Author

@Vollstrecker Thanks again — revised along the lines you were pointing at.

Dropped the optional zlib_bounds_safety.h helper and the CMake / Makefile ENABLE_FBOUNDS_SAFETY / ZLIB_ENABLE_FBOUNDS_SAFETY toggles. Those were what made the change look like an opt-in Clang-only feature and why CMake was touched even though the interesting path is the annotation itself.

Now inflate_state.window uses a native __attribute__((__sized_by_or_null__(wsize))) (with a __counted_by_or_null__ fallback) guarded by __has_attribute. On compilers that do not support the attribute, it is a no-op ordinary pointer, so default builds stay unchanged and there is no clang-only toggle to enable or misuse.

The remaining inflate.c edits are only the capacity-before-pointer / reset hygiene needed for the window↔wsize relationship. Diff is just inflate.h + inflate.c.

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