libdb 2026.09.8
A release-machinery correctness release. No engine changes. Every fix here came from
a pre-release audit conducted in the voices of the original Berkeley DB authors —
and the audit found, correctly, that the previous release had shipped defects in the
parts of the tree that fail silently.
The version triplet disagreed between build systems
dist/RELEASE says the compatibility triplet is 2026.0.9, but
dist/meson/db_subs.json had kept a stale hardcoded 5.3.37. So the meson build
emitted a db.h claiming 5.3.29 and produced a library that could not attach an
environment created by the autoconf build (env_region.c compares majver/minver
and returns DB_VERSION_MISMATCH).
Both abidiff and the region-signature gate stayed green through this, because each
build is internally consistent — neither gate compares across build systems.
dist/meson/gen_header.py now derives the triplet, DB_CALVER and
DB_RELEASE_DATE from dist/RELEASE, so the two paths cannot drift again. Verified
through this release's own version bump: both builds emit byte-identical
DB_VERSION_{STRING,MAJOR,MINOR,PATCH}.
An erratum on the compatibility covenant
VERSIONING.md, CONTRIBUTING.md and docs/design/global-invariants.md all stated
the level was "FROZEN at 5.3.37". That was never true of the shipped artifacts.
Commit 6710649f0 (2026-04-21) set the triplet to 2026.0.9 five months before
that covenant was written, so every release from v2026.04 onward has shipped
soname libdb-2026.0.so and stamped regions majver=2026. The documents described
an intention and nothing checked it against the code.
The freeze is real and still matters for the reasons those documents give — it is
simply frozen at 2026.0.9. db_version() returns triplet 2026,0,9, verified
against a built library rather than assumed. VERSIONING.md also showed an example
string ("Berkeley DB compat 5.3.37:") that the code has never produced; corrected.
dist/s_perm has been broken since VxWorks support was removed
s_perm's run() helper is fatal by design when a listed file is absent, and it
still listed dist/vx_buildcd, deleted in 022a557f9. So s_perm performed its
blanket find -type f | xargs chmod 644, restored a handful of bits, then aborted
before reaching dist/configure, config.guess, install-sh, dbinfo, mkpod
and the dtrace/systemtap scripts. A packaged tarball shipped dist/configure mode
644. It fails loudly when invoked, so nobody had invoked it — and the exec bits it
exists to protect simply decayed.
Additionally, upstream never restored exec bits on test/*.sh, because the Tcl suite
is driven by tclsh rather than by executing shell scripts. This fork's test tiers
are shell-driven and several are invoked as ./script, so the blanket chmod 644
was stripping them with nothing to put them back — 82 scripts were affected,
including the test/db/run_*.sh regression runners.
Fixed, with the test/ restoration placed before the allowlist, so a future
stale entry aborts after the bits are set rather than before. The discriminator is
the shebang, so test/harness.sh — which is sourced, not executed — correctly
stays 644.
dist/s_execbits is the verifying half, run from dist/s_all after s_test
following the s_include/s_sig/s_test convention. s_perm chmods a worktree at
packaging time and cannot see committed git modes; s_execbits checks exactly those.
Five duplicate message IDs — and a correction to our own audit
db_get_multiple() had copied DB_STR("0584") from a neighbouring call, and five
further ids were duplicated by earlier hardening commits: 1136, 1169 (zero-divisor
meta rejection), 3015 (planted DST durability bugs), 3037 (zero-pagesize
rejection) and 3672 (NULL-slot crash fix). Each had copied a nearby id along with
its string. All renumbered.
The audit's first pass got this wrong, and the qualifier caught it. An earlier
revision of test/KNOWN-ISSUES.md claimed all six remaining duplicates were
inherited from Oracle 5.3.28. Only one is. The error was checking whether each id
existed at v5.3.28 rather than whether it was duplicated there — five appear
once upstream and twice here. Corrected with an explicit erratum rather than a silent
edit.
New ids were allocated above each directory's observed maximum, not from
s_message_id's arithmetic range base — which would have assigned repmgr 3536,
below repmgr's actual floor of 3582.
The checker for that bug had never validated anything
dist/validate/s_chk_message_id uses bash arithmetic-for loops but declared
#!/bin/sh -. On Debian and Ubuntu, where /bin/sh is dash, it died at the first
loop having checked zero ids. On a developer box where /bin/sh is bash it appears
to work — which is exactly why this went unnoticed.
Worse, dist/s_validate invoked every checker as sh $t, overriding the shebang and
reintroducing the same failure. It now reads the first line and selects the
interpreter, without requiring an exec bit (the checkers are mode 644 by upstream
convention; all of them, verified before deciding).
And s_validate itself was referenced by no workflow — the same gap that hid
test/c/leak-run.sh for two releases. Now wired in as advisory, deliberately not
a hard gate: s_chk_err and s_chk_pubdef print their failures and exit 0 (their
exit 1 sits inside a subshell), so gating on s_validate today would be
green-by-accident. That is tracked as U1.
db_get_multiple() was not exported on Windows
Declared in build_windows/db.h but absent from dist/win_exports.in, so neither
libdb.def nor libdb_small.def exported it — a link error for every Windows
consumer, with no compile-time signal.
Added at the end of the public block, not alphabetically: .def exports are
ordinal-based ABI, and an alphabetical insert renumbered db_strerror 10→11 and
db_version 11→12, which would have silently broken every consumer linking by
ordinal. Only test-only __repmgr_getaddr shifts. libdb_small.def had been missed
on the first attempt and is included now.
Known issues
test/KNOWN-ISSUES.md tracks all of these. Two new entries:
U6— the meson build is not feature-parity with autoconf.meson setupomits
tenHAVE_*flags thatconfiguredetects, includingHAVE_ATOMIC_SUPPORT,
HAVE_IO_URINGandHAVE_AIO_*. Several change struct layout, so
__env_struct_sig()differs and a cross-build environment attach failsBDB1539.
Pre-existing: the same drift exists atv2026.09.7, where a different error
(BDB1538, wrong triplet) masked it. Fixing the triplet removedBDB1538and left
BDB1539visible — two independent defects stacked, and this release fixes one.
The meson path is a convenience build, not a supported artifact, and
meson/autoconf environment interoperability is explicitly not claimed.U1–U5— inherited Oracle defects, notably the twodist/validatecheckers
that print failures and exit 0.
Unchanged and still open: P1 (the PGNO_BASE_MD allocation convoy), T1–T6,
S1 (opt-in DB_MPOOL_AIO), S5, W1, B1.
Compatibility
No on-disk, log, region, or public-ABI change. __env_struct_sig() is unchanged at
0xb86f77f0; public sizes remain 1744/552/2088/336. Existing environments attach
unchanged. The compatibility triplet stays 2026.0.9; 2026.09.8 is the release
identity.