Library

zxc v0.13.3

Versionv0.13.3
Stars★ 432
Released2026-08-17

Seekable lossless compression with O(1) random access, built for ultra-fast decode. Faster than LZ4 (40%+ on ARM64), with better ratios. C library, write-once/read-many.

Release notes

# Release Notes

v0.13.3 is a hardening and packaging release.

The headline isn't really in the code: **ZXC is now enrolled in Google OSS-Fuzz**, which runs five harnesses around the clock. It has already turned up two decoder edge cases, both fixed here. Neither is reachable from an archive ZXC itself produced — you need a hand-crafted file to hit them — but a decompressor that can be walked out of its buffer is a decompressor worth fixing.

The rest is housekeeping. The GHI header's `enc_off` field is now formally unused, which is the ambiguity that let the first bug through; match-offset validation lost a counter it never needed; and static linking on Windows works again.

**Nothing changes in the format or the ABI.** v0.13.3 reads and writes the same format v7 archives as the rest of the v0.13.x line, and the soname is still `libzxc.so.4`.

> **Drop-in for v0.13.x.** No format break, no ABI change, nothing to re-link. Archives move both ways between v0.13.3 and any earlier v0.13.x release. One detail worth knowing: at levels 1 and 2 the encoder now writes the unused `enc_off` GHI header field as `0` rather than `1`, so output at those levels is no longer byte-for-byte what v0.13.2 produced. It is still standard  format v7, and every v0.13.x release reads it. Levels 3-7 are byte-identical.

## Reliability & Security Fixes

### Out-of-bounds read on forged GHI offsets (decoder)

The GHI safe loop took its offset-validation threshold from the `enc_off` header field: 256 bytes when `enc_off == 1`. That field never described GHI offsets, which live inline in the sequence word and are always 16 bits wide. So a crafted archive could claim `enc_off = 1`, carry a much larger offset, and once 256 bytes had been written the loop simply stopped checking — and the copy read from before the start of the output buffer. The threshold is now the 16-bit bound, unconditionally. Found by OSS-Fuzz ([544800535](https://issues.oss-fuzz.com/issues/544800535)). (#367)

### Output-buffer overflow on escaped literal lengths (decoder)

When a sequence escapes its literal length into a varint, the GLO and GHI decode macros used to check that the literals fit in the remaining output space — and nothing else. They ignored the match length that follows, and the output still owed by the rest of the batch. A crafted archive could clear that check and then write past the end of the destination buffer. Both macros now weigh literals, match length and the batch remainder together, and the trailing-literal copy has an explicit guard in front of it. Found by OSS-Fuzz ([546426939](https://issues.oss-fuzz.com/issues/546426939)). (#369)

### `enc_off` is unused in GHI blocks and must be ignored

#367 was really a spec problem, so the field is now nailed down on both sides. The compressor always writes `enc_off = 0` in GHI headers, and `FORMAT.md` says decoders **must ignore** it. GHI has no offset stream and its sequence words always carry 16-bit offsets, so there is nothing for the field to bound. (#368)

### Stale dictionary size on a reused compression context

`zxc_compress_cctx()` never reset `dict_size`. Reuse a context after a dictionary compression and the old dictionary size came along for the ride into the next, plain one. It is reset on every call now. (#351)

## Performance

### Leaner match-offset validation

Match-offset validation used to lean on a running count of bytes written, updated on every single sequence. That counter is gone. The decoder now compares the match source directly to the start of the output buffer, or of the dictionary prefix when one is attached. Same guarantee, less bookkeeping in the hot loop. (#368)

## Build, Packaging & Portability

### Windows static-library linking

`__declspec(dllimport)` and static libraries don't get along on Windows: the link fails outright. `ZXC_DLL_IMPORT` is opt-in from now on, so plain declarations link against both the DLL and the static library. CMake, M…

Share this resource


Discovered 2026-08-18 Source GitHub Archive 2026-08 →