Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package apko for openSUSE:Factory checked in at 2026-07-03 16:04:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/apko (Old) and /work/SRC/openSUSE:Factory/.apko.new.1982 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apko" Fri Jul 3 16:04:40 2026 rev:122 rq:1363549 version:1.2.21 Changes: -------- --- /work/SRC/openSUSE:Factory/apko/apko.changes 2026-07-01 16:47:43.792195674 +0200 +++ /work/SRC/openSUSE:Factory/.apko.new.1982/apko.changes 2026-07-03 16:07:59.795688337 +0200 @@ -1,0 +2,7 @@ +Thu Jul 02 16:37:37 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 1.2.21: + * fix(ldso-cache): Order cache entries to match ld.so's search + (#2311) + +------------------------------------------------------------------- Old: ---- apko-1.2.20.obscpio New: ---- apko-1.2.21.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ apko.spec ++++++ --- /var/tmp/diff_new_pack.sQNqvq/_old 2026-07-03 16:08:02.891796254 +0200 +++ /var/tmp/diff_new_pack.sQNqvq/_new 2026-07-03 16:08:02.895796394 +0200 @@ -17,7 +17,7 @@ Name: apko -Version: 1.2.20 +Version: 1.2.21 Release: 0 Summary: Build OCI images from APK packages directly without Dockerfile License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.sQNqvq/_old 2026-07-03 16:08:02.951798345 +0200 +++ /var/tmp/diff_new_pack.sQNqvq/_new 2026-07-03 16:08:02.955798485 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/chainguard-dev/apko.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">refs/tags/v1.2.20</param> + <param name="revision">refs/tags/v1.2.21</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.sQNqvq/_old 2026-07-03 16:08:02.987799601 +0200 +++ /var/tmp/diff_new_pack.sQNqvq/_new 2026-07-03 16:08:02.991799740 +0200 @@ -3,6 +3,6 @@ <param name="url">https://github.com/chainguard-dev/apko</param> <param name="changesrevision">861f83f69e6fa9114405a2f7bb5cf6585ad00421</param></service><service name="tar_scm"> <param name="url">https://github.com/chainguard-dev/apko.git</param> - <param name="changesrevision">589da44360c7ffc7a5c1d9219bbbff750d614dc4</param></service></servicedata> + <param name="changesrevision">403a40e1ee97f924e9448f947100fb314ac820fb</param></service></servicedata> (No newline at EOF) ++++++ apko-1.2.20.obscpio -> apko-1.2.21.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-1.2.20/internal/ldso-cache/ldsocache.go new/apko-1.2.21/internal/ldso-cache/ldsocache.go --- old/apko-1.2.20/internal/ldso-cache/ldsocache.go 2026-06-30 10:51:32.000000000 +0200 +++ new/apko-1.2.21/internal/ldso-cache/ldsocache.go 2026-07-02 13:39:22.000000000 +0200 @@ -17,6 +17,7 @@ import ( "bufio" "bytes" + "cmp" "debug/elf" "encoding/binary" "errors" @@ -26,7 +27,6 @@ "log" "path/filepath" "slices" - "sort" "strings" "unsafe" ) @@ -351,15 +351,55 @@ allEntries = append(allEntries, entries...) } - // ld expects entries to be reverse-sorted by name. Otherwise - // it may report "No such file or directory" - sort.Slice(allEntries, func(i, j int) bool { - return filepath.Base(allEntries[j].Name) < filepath.Base(allEntries[i].Name) + // The dynamic linker binary-searches /etc/ld.so.cache using + // _dl_cache_libcmp, so entries must be ordered by that same comparison or + // ld.so may fail to find a library that is present in the cache (reporting + // "cannot open shared object file"). glibc's ldconfig emits entries in + // descending order, so we negate the comparison. + slices.SortFunc(allEntries, func(entry, other LDSOCacheEntry) int { + return -dlCacheLibcmp(filepath.Base(entry.Name), filepath.Base(other.Name)) }) return allEntries, nil } +func isDigit(c byte) bool { return c >= '0' && c <= '9' } + +// dlCacheLibcmp mirrors glibc's _dl_cache_libcmp (elf/dl-cache.c), the +// comparison the dynamic linker uses to binary-search /etc/ld.so.cache. Runs of +// digits are compared numerically, and a digit is considered greater than any +// non-digit at the same position. It returns a negative number, 0, or a +// positive number as libName is less than, equal to, or greater than otherName. +func dlCacheLibcmp(libName, otherName string) int { + pos, otherPos := 0, 0 + for pos < len(libName) && otherPos < len(otherName) { + switch char, otherChar := libName[pos], otherName[otherPos]; { + case isDigit(char) && isDigit(otherChar): + // Compare the two version-number runs numerically. + var version, otherVersion int + for ; pos < len(libName) && isDigit(libName[pos]); pos++ { + version = version*10 + int(libName[pos]-'0') + } + for ; otherPos < len(otherName) && isDigit(otherName[otherPos]); otherPos++ { + otherVersion = otherVersion*10 + int(otherName[otherPos]-'0') + } + if version != otherVersion { + return cmp.Compare(version, otherVersion) + } + case isDigit(char): + return 1 // a digit outranks a non-digit + case isDigit(otherChar): + return -1 + case char != otherChar: + return cmp.Compare(char, otherChar) + default: + pos, otherPos = pos+1, otherPos+1 + } + } + // Whichever name still has characters left is the greater one. + return cmp.Compare(len(libName)-pos, len(otherName)-otherPos) +} + func BuildCacheFileForDirs(fsys fs.FS, libdirs []string) (*LDSOCacheFile, error) { entries, err := LDSOCacheEntriesForDirs(fsys, libdirs) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-1.2.20/internal/ldso-cache/ldsocache_test.go new/apko-1.2.21/internal/ldso-cache/ldsocache_test.go --- old/apko-1.2.20/internal/ldso-cache/ldsocache_test.go 2026-06-30 10:51:32.000000000 +0200 +++ new/apko-1.2.21/internal/ldso-cache/ldsocache_test.go 2026-07-02 13:39:22.000000000 +0200 @@ -195,3 +195,30 @@ require.GreaterOrEqual(t, prev, cur) } } + +func Test_dlCacheLibcmp_DigitVsNonDigit(t *testing.T) { + // A digit outranks a non-digit at the same position (glibc semantics): + // "libyaml-0.so.2" > "libyaml-cpp.so.0.8" because '0' > 'c'. + require.Greater(t, dlCacheLibcmp("libyaml-0.so.2", "libyaml-cpp.so.0.8"), 0) + require.Less(t, dlCacheLibcmp("libyaml-cpp.so.0.8", "libyaml-0.so.2"), 0) + // Digit runs compare numerically, not lexically: ".so.9" < ".so.10". + require.Less(t, dlCacheLibcmp("libfoo.so.9", "libfoo.so.10"), 0) + require.Equal(t, 0, dlCacheLibcmp("libfoo.so.13", "libfoo.so.13")) +} + +func Test_LDSOCacheEntriesForDirs_SortMatchesDlCacheLibcmp(t *testing.T) { + getElfInfo = mockGetElfInfo + root := os.DirFS("testdata/libroot") + libdirs, err := ParseLDSOConf(root, "etc/ld.so.conf") + require.NoError(t, err) + entries, err := LDSOCacheEntriesForDirs(root, libdirs) + require.NoError(t, err) + // Entries must be in descending _dl_cache_libcmp order so ld.so's binary + // search over the cache succeeds. + for i := 1; i < len(entries); i++ { + a := filepath.Base(entries[i-1].Name) + b := filepath.Base(entries[i].Name) + require.GreaterOrEqual(t, dlCacheLibcmp(a, b), 0, + "entries not in descending _dl_cache_libcmp order: %q before %q", a, b) + } +} ++++++ apko.obsinfo ++++++ --- /var/tmp/diff_new_pack.sQNqvq/_old 2026-07-03 16:08:04.039836270 +0200 +++ /var/tmp/diff_new_pack.sQNqvq/_new 2026-07-03 16:08:04.051836689 +0200 @@ -1,5 +1,5 @@ name: apko -version: 1.2.20 -mtime: 1782809492 -commit: 589da44360c7ffc7a5c1d9219bbbff750d614dc4 +version: 1.2.21 +mtime: 1782992362 +commit: 403a40e1ee97f924e9448f947100fb314ac820fb ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/apko/vendor.tar.gz /work/SRC/openSUSE:Factory/.apko.new.1982/vendor.tar.gz differ: char 13, line 1
