Skip to content

Commit 868d3f9

Browse files
committed
dlopen-notes: make output stable regardless of order of inputs
When multiple files are passed to dlopen-notes --sonames the output depends on the order of inputs in case the same soname is used with different priorities across different binaries: $ ./dlopen-notes.py --sonames systemd-sbsign systemd-repart libblkid.so.1 required libcrypto.so.3 recommended libcryptsetup.so.12 recommended libfdisk.so.1 required libmount.so.1 required $ ./dlopen-notes.py --sonames systemd-repart systemd-sbsign libblkid.so.1 required libcrypto.so.3 required libcryptsetup.so.12 recommended libfdisk.so.1 required libmount.so.1 required sbsign requires libcrypto, and repart recommends it, so the output changes between required and recommended depending on which is passed last. Fix it so that the highest priority for any given soname is always returned, regardless of the number of input binaries.
1 parent 885cacb commit 868d3f9

2 files changed

Lines changed: 32 additions & 10 deletions

File tree

dlopen-notes.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ def notes(self):
6969

7070
yield from j
7171

72-
@dictify
7372
def group_by_soname(elffiles):
73+
sonames = {}
7474
for elffile in elffiles:
7575
for element in elffile.notes():
76-
priority = element.get('priority', 'recommended')
76+
priority = Priority[element.get('priority', 'recommended')]
7777
for soname in element['soname']:
78-
yield soname, priority
78+
sonames[soname] = max(sonames.get(soname, priority), priority)
79+
80+
return sonames
7981

8082
class Priority(enum.Enum):
8183
suggested = 1
@@ -85,6 +87,9 @@ class Priority(enum.Enum):
8587
def __lt__(self, other):
8688
return self.value < other.value
8789

90+
def __str__(self):
91+
return self.name
92+
8893
def rpm_name(self):
8994
if self == self.__class__.suggested:
9095
return 'Suggests'

test/test.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# SPDX-License-Identifier: CC0-1.0
22

3-
from _notes import ELFFileReader, group_by_soname, generate_rpm
3+
from _notes import ELFFileReader, group_by_soname, generate_rpm, Priority
44

55
def test_sonames():
66
expected = {
7-
'libfido2.so.1': 'required',
8-
'liblz4.so.1': 'recommended',
9-
'libpcre2-8.so.0': 'suggested',
10-
'libpcre2-8.so.1': 'suggested',
11-
'libtss2-esys.so.0': 'recommended',
12-
'libtss2-mu.so.0': 'recommended',
7+
'libfido2.so.1': Priority.required,
8+
'liblz4.so.1': Priority.recommended,
9+
'libpcre2-8.so.0': Priority.suggested,
10+
'libpcre2-8.so.1': Priority.suggested,
11+
'libtss2-esys.so.0': Priority.recommended,
12+
'libtss2-mu.so.0': Priority.recommended,
1313
}
1414
notes = ELFFileReader('notes')
1515
assert group_by_soname([notes]) == expected
@@ -33,3 +33,20 @@ def test_requires():
3333
lines = generate_rpm([notes], 'Suggests', ('pcre2', 'tpm'))
3434
expect = expected[notes.elffile.elfclass]
3535
assert sorted(lines) == sorted(expect)
36+
37+
class FakeReader:
38+
def __init__(self, notes):
39+
self._notes = notes
40+
41+
def notes(self):
42+
return self._notes
43+
44+
def test_sonames_highest_priority_stable():
45+
a = FakeReader([{'soname': ['libcrypto.so.3'], 'priority': 'required'}])
46+
b = FakeReader([{'soname': ['libcrypto.so.3'], 'priority': 'recommended'}])
47+
c = FakeReader([{'soname': ['libcrypto.so.3'], 'priority': 'suggested'}])
48+
49+
expected = {'libcrypto.so.3': Priority.required}
50+
assert group_by_soname([a, b, c]) == expected
51+
assert group_by_soname([c, b, a]) == expected
52+
assert group_by_soname([b, a, c]) == expected

0 commit comments

Comments
 (0)