Package: libcurl3-gnutls
Version: 7.85.0-1
Severity: normal

libcurl3-gnutls announces its SONAME as libcurl-gnutls.so.4, the same
as upstream libcurl, but its symbols are versioned as CURL_GNUTLS_3,
not the same as upstream libcurl (where they would be CURL_GNUTLS_4).
This is contrary to the usual design principle that SONAMEs and versioned
symbols should be managed by upstream projects (with assistance from
downstreams where it becomes necessary), and broadly compatible between
dissimilar downstream distributions.

This breaks the following scenarios, which can never be entirely
guaranteed to work but in practice do work for most other libraries,
like for example GTK or SDL:

* compile a relocatable binary against Debian's libcurl4-gnutls-dev
* attempt to run it against an equal or newer version of upstream libcurl
  that was built with versioned symbols and GNUTLS as SSL backend
* expected result: it runs successfully
* actual result: runtime linking fails because the binary is looking for
  symbols like curl_global_init@CURL_GNUTLS_3, but upstream libcurl only
  provides curl_global_init@CURL_GNUTLS_4

and conversely

* compile a relocatable binary against an upstream libcurl that was built
  with versioned symbols and GNUTLS as SSL backend
* attempt to run it against an equal or newer version of Debian's
  libcurl3-gnutls
* expected result: it runs successfully
* actual result: runtime linking fails because the binary is looking for
  symbols like curl_global_init@CURL_GNUTLS_4, but Debian's libcurl only
  provides curl_global_init@CURL_GNUTLS_3

This particularly affects LD_LIBRARY_PATH environments that are careful to
choose each library to be either the system copy or the locally-bundled
copy, whichever is newer, in order to avoid version conflicts (such as
Valve's Steam Runtime): on Debian systems, a newer system copy is
non-backwards-compatible with an older upstream libcurl, and conversely
a newer upstream libcurl is non-backwards-compatible with binaries built
against an older Debian derivative like the Steam Runtime.

The OpenSSL flavour of libcurl had an equivalent incompatibility between
about 2005 and 2018, but the Debian and upstream ABIs re-converged in
2018 during the switch from OpenSSL 1.0 to 1.1.

The NSS flavour of libcurl might have the same issue, but this is
mitigated by the fact that to the best of my knowledge, nobody else links
libcurl to NSS.

I think the ideal solution would go something like this:

* re-converge on upstream's ABI, with symbols like
  curl_global_init@CURL_GNUTLS_4
* make those symbols the default implementation (sometimes seen written as
  "curl_global_init@@CURL_GNUTLS_4" with a double @ sign), so that new
  binaries linked against either upstream or downstream libcurl want to see
  symbols like curl_global_init@CURL_GNUTLS_4 at runtime
* for backwards compatibility with older Debian, also export each symbol
  that existed prior to this transition, as curl_global_init@CURL_GNUTLS_3
  or similar, either as aliases for the upstream-compatible symbols or as
  shims that pass on their arguments to the upstream-compatible symbols;
  there is a finite (but large) number of such symbols
* make the ...@CURL_GNUTLS_3 symbols non-default (sometimes seen written as
  "(curl_global_init@CURL_GNUTLS_3)" in parentheses), so that newly-linked
  binaries do not expect to see these symbols
* ideally send the compatibility shims upstream so that after enough time
  has passed, everyone's GNUTLS builds of libcurl end up implementing
  both ABIs

This is probably too intrusive to do before Debian 12, since the freeze is
only a few months away, but it would be good to re-converge with upstream
at some point in future.

    smcv

Reply via email to