From 49189d802a363c6e5f80f77d3909fac3dad16093 Mon Sep 17 00:00:00 2001 From: jslobodzian Date: Tue, 25 Aug 2026 13:24:50 -0400 Subject: [PATCH] Sodiff: detect name-embedded-version soname transitions (thrift, LLVM) Sodiff normalized only versions trailing ".so" (libfoo.so.), so libraries that bake the version into the base name (libthrift-0.24.0.so, libLLVM-18.so) were treated as brand-new libraries. Their predecessor was never found, the --whatrequires dependent scan was skipped, and orphaned dependents (e.g. parquet-libs still requiring libthrift-0.15.0.so after the thrift 0.15->0.24 bump in PR #18239) passed the check -- later breaking dependent builds such as ceph (seen in PR #18543). Derive the version-independent .so "family" for both SONAME styles when locating a published predecessor and its requirers. Bug: 23439 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 17152c7d-ff27-432d-b038-1ad05da30e3c --- toolkit/scripts/sodiff/mariner-sodiff.sh | 27 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/toolkit/scripts/sodiff/mariner-sodiff.sh b/toolkit/scripts/sodiff/mariner-sodiff.sh index 3076fcf33b7..ef8b5b8379f 100755 --- a/toolkit/scripts/sodiff/mariner-sodiff.sh +++ b/toolkit/scripts/sodiff/mariner-sodiff.sh @@ -65,14 +65,30 @@ for rpmpackage in $pkgs; do # SO file not found, meaning this might be a new .SO # or a new version of a preexisting .SO. # Check if the previous version exists in the database. + # + # Derive a version-independent "family" pattern for the .so so we can + # locate a predecessor already published in the repo. Two SONAME + # styles must be handled: + # 1. Conventional: libfoo.so. -> family "libfoo.so" + # 2. Name-embedded: libfoo-.so -> family "libfoo-*.so" + # Style 2 is used by libraries whose ABI is versioned by package + # version (e.g. Apache Thrift's libthrift-0.24.0.so, LLVM's + # libLLVM-18.so). For these, every version bump is a SONAME change, + # so the changing version lives in the library *base name*. The old + # logic only stripped a version that trailed ".so", so it treated + # every such release as a brand-new library and never scanned for + # orphaned dependents that still required the previous version. + sofile_base=$(echo "$sofile" | sed -E 's/[(].*$//') + if echo "$sofile_base" | grep -qE '^.*-[0-9][0-9.]*[.]so$' ; then + sofile_no_ver=$(echo "$sofile_base" | sed -E 's/-[0-9][0-9.]*[.]so$/-*.so/') + else + sofile_no_ver=$(echo "$sofile_base" | sed -E 's/[.]so[.].*$/.so/') + fi - # Remove version part from .SO file - sofile_no_ver=$(echo "$sofile" | sed -E 's/[.]so[(.].+/.so/') - - # check for generic .so in the repo + # check for a prior version of this .so family in the repo sos_found=$( 2>/dev/null $dnf_command repoquery $common_options --whatprovides "${sofile_no_ver}*" | wc -l ) if ! [ "$sos_found" -eq 0 ] ; then - # Generic version of SO was found. + # A prior version of the SO family was found. # This means it's a new version of a preexisting SO. # Log which packages depend on this functionality echo "Packages that require $sofile_no_ver:" @@ -120,4 +136,3 @@ if [[ $pkgsFound -gt 0 ]]; then else echo "No Packages with Conflicting .so Files Found." fi -