Skip to content

Commit de9169f

Browse files
committed
dependencies: fix graph_reverse_depends crash on Atom.intersects
Atom.intersects() type-checks its argument since portage removed str subtyping from Atom, so it needs a real Atom object, not a Dependencies (a Query subclass) or a plain string. graph_reverse_depends() called dep.intersects(self) where self is a Dependencies object. Pass self.atom instead, but that then exposed a second bug: gentoolkit.atom.Atom.__init__ sets self.atom to the raw atom string it was constructed from (used by __repr__/__str__). Query.__init__ copied that string into self.atom via __dict__.update(), and its fallback except branch set self.atom = self.cpv (also a plain string), so Query.atom was never actually usable as an Atom. Fix both: restore self.atom to the real Atom object in the success path, and construct one from self.cpv in the fallback path. That still leaves bare package-name queries (e.g. "simdjson") crashing: they parse as neither a valid atom nor a valid CPV, so Query.__init__ falls back further to a plain string in self.atom, which Atom.intersects() can't type-check. Since gentoolkit's Atom can't represent a name-only atom at all (portage.dep.Atom rejects it), graph_reverse_depends() now passes self instead of self.atom whenever self.atom isn't a real Atom. self already carries the .cp/.category/.name attributes intersects() needs for its name-only comparison, and since self.cp (unslashed) never equals dep.cp ("cat/pkg"), that comparison always takes the early-return branch, so the attributes intersects() doesn't check (.repo, .slot, etc.) are never touched. Bug: https://bugs.gentoo.org/981521 Signed-off-by: Matt Turner <mattst88@gentoo.org>
1 parent 58cac13 commit de9169f

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

pym/gentoolkit/dependencies.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ def graph_reverse_depends(
227227
if seen is None:
228228
seen = set()
229229

230+
# self.atom is a real Atom only when the query parsed as a valid
231+
# atom; a bare package name (e.g. "simdjson") falls back to a plain
232+
# string that Atom.intersects() can't type-check. Pass self instead:
233+
# it has the .cp/.category/.name attributes intersects() needs for
234+
# its name-only comparison, and since self.cp (unslashed) never
235+
# equals dep.cp ("cat/pkg"), that comparison always takes the
236+
# early-return branch, so the attributes intersects() doesn't check
237+
# (.repo, .slot, etc.) are never touched.
238+
target = self.atom if isinstance(self.atom, Atom) else self
239+
230240
for pkgdep in (Dependencies(pkg) for pkg in pkgset):
231241
if self.cp not in pkgdep.get_raw_depends():
232242
# fast path for obviously non-matching packages. This saves
@@ -236,7 +246,7 @@ def graph_reverse_depends(
236246

237247
found_match = False
238248
for dep in pkgdep.get_all_depends():
239-
if dep.intersects(self):
249+
if dep.intersects(target):
240250
pkgdep.depatom = dep
241251
pkgdep.depth = depth
242252
yield pkgdep

pym/gentoolkit/query.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def __init__(self, query, is_regex=False):
6060
try:
6161
atom = Atom(self.query)
6262
self.__dict__.update(atom.__dict__)
63+
# gentoolkit.atom.Atom.__init__ sets self.atom to the raw
64+
# atom string (for __repr__/__str__), clobbering what should
65+
# be a reference to the Atom object itself; restore it.
66+
self.atom = atom
6367
# portage.dep.Atom uses __slots__, so cpv, _cp, and _version
6468
# are absent from atom.__dict__; initialize them explicitly so
6569
# CPV's lazy property accessors don't raise AttributeError.
@@ -75,7 +79,13 @@ def __init__(self, query, is_regex=False):
7579
except errors.GentoolkitInvalidAtom:
7680
CPV.__init__(self, self.query)
7781
self.operator = ""
78-
self.atom = self.cpv
82+
# self.cpv may contain glob/regex wildcards (e.g. from a
83+
# regex query), which aren't valid atom syntax; fall back to
84+
# the plain string in that case.
85+
try:
86+
self.atom = Atom(f"={self.cpv}")
87+
except errors.GentoolkitInvalidAtom:
88+
self.atom = self.cpv
7989

8090
def __repr__(self):
8191
rx = ""

0 commit comments

Comments
 (0)