gzip wordlists fail to open on macOS: ext_zlib.c requires gzopen64, which Apple's libz does not export
Describe the bug
Since zlib moved to runtime loading in src/ext_zlib.c, gzip-compressed wordlists and hashlists
cannot be opened on macOS. ZLIB_SYMS marks gzopen64, gzseek64 and gztell64 as required
symbols, and Apple's system libz exports none of them.
The comment above the table explains the intent: zlib's header renames gzopen to gzopen64
through a macro when the build enables the large file API, and dlsym cannot follow a macro, so the
suffixed names are written out literally.
That reasoning holds on glibc but not on Darwin. off_t on macOS is already 64 bit, so zlib's
configure never enables _LARGEFILE64_SOURCE and the library emits no *64 aliases at all.
/usr/lib/libz.1.dylib exports gzopen, gzseek and gztell and nothing named gzopen64.
Requiring the suffixed spelling refuses a library that is fully capable of what hashcat asks of it.
The suggested remedy in the error message (brew install zlib) does not help. Homebrew builds the
same upstream source with stock configure on the same platform, so its libz has the same export set.
This would not show up in CI, since every glibc box has the LFS aliases.
To Reproduce
On macOS, with any gzip wordlist:
hashcat -m 2100 left.hashes.txt wordlist.txt.gzhashcat (v7.1.2-676-ge6a7f642c) starting
METAL API (Metal 373.7)
=======================
* Device #01: Apple M2 Max, skipped
OpenCL API (OpenCL 1.2 (Jul 31 2026 20:36:30)) - Platform #1 [Apple]
====================================================================
* Device #02: Apple M2 Max, GPU, 79562/79626 MB (7464 MB allocatable), 38MCU
wordlist.txt.gz: gzip support is unavailable: gzopen64 is missing from the shared library. To fix this, install zlib, for example with: brew install zlibThe export set can be confirmed without building anything:
python3 -c "
import ctypes
l = ctypes.CDLL('libz.1.dylib')
print({s: hasattr(l, s) for s in ('gzopen','gzopen64','gzseek64','gztell64')})
"
{'gzopen': True, 'gzopen64': False, 'gzseek64': False, 'gztell64': False}Expected behavior
A gzip wordlist opens on macOS against the system libz, as it did when zlib was vendored and statically linked.
Suggested fix
Try the suffixed names first, then fall back to the plain ones, gated to platforms where off_t is
known to be 64 bit. The gate is not cosmetic: on a 32 bit build without _FILE_OFFSET_BITS=64 the
unsuffixed entry points take and return a 32 bit offset, and reaching one through a prototype
declaring long long would put the wrong width on the wire. Darwin has no such configuration left,
so __APPLE__ is a safe gate.
A patch doing this is attached. It makes the three symbols optional only where the fallback is
compiled in, adds a second symbol table using the existing HC_DYNLIB_SYM_AS macro, and consults it
only when one of the suffixed names is absent. On glibc nothing changes: the suffixed names stay
required and are still preferred.
Verified by linking the real ext_zlib.c and dynloader.c against stub libraries with controlled
export sets:
| libz export set | fallback compiled out | fallback compiled in |
|---|---|---|
| Darwin-like (plain only) | fails: gzopen64 is missing ... |
loads, slot resolves gzopen |
| glibc-like (both spellings) | loads via gzopen64 |
loads via gzopen64 |
| neither spelling | fails | fails, names gzopen |
Row 1 reproduces the reported failure; row 2 confirms glibc behaviour is unchanged.
Hardware
- Apple M2 Max
- Metal 373.7 / OpenCL 1.2 (Apple)
Version
- hashcat v7.1.2-676-ge6a7f642c
- macOS 26.6.2 (25G83), arm64
Additional context
Unaffected on the v7.1.2 release, where zlib is still vendored and statically linked. The regression
is limited to builds carrying the runtime-loaded src/ext_zlib.c.
Source: hashcat/hashcat