PostgreSQL and OpenSSL 4.0.0

First seen: 2026-04-16 13:32:54+00:00 · Messages: 9 · Participants: 4

Latest Update

2026-05-08 · opus 4.7

Core Problem: OpenSSL 4.0.0 API Const-Correctness Churn

OpenSSL 4.0.0 shipped GA in April 2026 and — while not removing any APIs PostgreSQL currently relies on — tightened const qualifiers on a number of function signatures used by libpq and contrib/sslinfo. This is a classic cross-version portability trap: the signatures differ between OpenSSL 1.0.1, 1.0.2, 1.1.1, 3.x, 4.0.0, and LibreSSL's divergent tree. Simply adopting const in PostgreSQL's call sites to match 4.0.0 immediately generates "discards qualifiers" warnings when building against 1.1.1 or LibreSSL, and vice versa.

The architectural significance is not the warnings themselves but what they portend. PostgreSQL's TLS layer is one of very few places where the backend directly interfaces with an external, independently-versioned C library whose ABI/API is a moving target. Each OpenSSL major release has historically required intrusive adaptation (opaque structs in 1.1.0, provider model in 3.0, deprecations escalating in 3.x). The thread is the opening salvo of what Daniel Gustafsson signals will be a larger effort: 4.0.0 also deprecates more APIs PostgreSQL uses, to be handled in follow-up threads.

Proposed Solution and Its Ugliness

The patch deliberately does not propagate const through PostgreSQL's code. Instead, it applies cast-away-constness at the call boundary so the same source compiles warning-free against the union of supported OpenSSL/LibreSSL variants. Gustafsson himself calls it "not pretty" and acknowledges "uglier tricks with casting away constness" are necessary because the constness varies non-monotonically across versions (i.e., not all newer versions added const — LibreSSL diverges differently).

This is the pragmatic choice. The alternative — conditional compilation keyed on OPENSSL_VERSION_NUMBER and LIBRESSL_VERSION_NUMBER for each affected signature — would multiply preprocessor branches and be even harder to maintain given LibreSSL's independent versioning that sometimes lies about its OpenSSL compatibility macro.

A secondary fix emerged from Cary Huang's testing: OpenSSL 4.0.0 changed the wording in a TLS alert diagnostic from "ssl alert certificate revoked" to "tls alert certificate revoked". The SSL regression tests matched the literal string, so the expected output needed updating. Gustafsson had already folded this into a later revision of the patchset.

Key Design Decision: Backpatch Scope

The bulk of the technical discussion is not about the patch itself but about how far to backpatch. Two positions emerge:

  1. Daniel Gustafsson's initial lean: Do not backpatch to REL_14. His reasoning is asymmetric risk — if something breaks on 14 against OpenSSL 4, the branch is near EOL and the project cannot commit to chasing further fixes. He proposes simply documenting in 14 that OpenSSL 3.6 is the newest supported version.

  2. Michael Paquier's counter: This creates an unacceptable user-facing situation. A site running REL_14_STABLE + OpenSSL 1.0.1 would, on taking a normal minor update, be told either "upgrade OpenSSL to 3.6+" (a major operational change) or "wait six months for the next minor". Neither is acceptable for a stable branch.

  3. Tom Lane's resolution (authoritative): Push to all branches including 14, but immediately after next week's minor releases rather than squeezed in before them. This gives three months of buildfarm and user exposure before the next release window. Lane explicitly notes the calculus: he would side with Gustafsson (skip 14) if only one 14 release remained, but with two releases remaining (August and November) there is still a safety valve if a regression escapes notice.

Lane's input effectively closes the debate. As a senior committer and RMT voice, his framing — "too high-risk to shove in just before a release, but shortly after one is ideal" — is the de facto policy for high-surface-area portability patches.

Version Support Landscape

Gustafsson lays out the support matrix, which is important context for why this is pressing:

This means the patch must span a range from 1.0.1 to 4.0.0 on older branches — roughly a decade of API evolution. The constness casting approach is the only realistic way to maintain a single code path across that spread.

Technical Implications

Who Carries Weight