From 4180f82f2eb0f5eb6657c42a36f183c1ea889ff1 Mon Sep 17 00:00:00 2001 From: Kyle Walker Date: Mon, 24 Oct 2022 08:57:34 -0400 Subject: [PATCH 1/2] query-py: Ensure reldep is from the same sack When using two Base() modules, it is possible that a Reldep is referenced across sack instances. Example: base1 = dnf.Base() base1.read_all_repos() base1.fill_sack() base2 = dnf.Base() base2.read_all_repos() base2.fill_sack() pkg = base1.sack.query().filter(name='glibc').latest()[0] for req in pkg.requires: base2.sack.query().filter(provides=req) // Should FAIL The Reldep object from the "req" is sack-specific. This commit changes the above into a failure condition by verifying that the Query and Reldep come from the same sack. In the event that they do not, it raises the following error: "Direct dependency lookups must originate from the same sack." Signed-off-by: Kyle Walker Conflict:NA Reference:https://github.com/rpm-software-management/libdnf/pull/1583 --- libdnf/repo/solvable/Dependency.hpp | 2 ++ python/hawkey/query-py.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/libdnf/repo/solvable/Dependency.hpp b/libdnf/repo/solvable/Dependency.hpp index 47859e65ab..a5dde3dbd6 100644 --- a/libdnf/repo/solvable/Dependency.hpp +++ b/libdnf/repo/solvable/Dependency.hpp @@ -63,6 +63,7 @@ struct Dependency const char *getVersion() const; const char *toString() const; Id getId() const noexcept; + DnfSack * getSack() const noexcept; private: friend DependencyContainer; @@ -92,6 +93,7 @@ struct Dependency }; inline Id Dependency::getId() const noexcept { return id; } +inline DnfSack * Dependency::getSack() const noexcept { return sack; } } diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp index 99f71bd5fc..a25a0d6bd2 100644 --- a/python/hawkey/query-py.cpp +++ b/python/hawkey/query-py.cpp @@ -345,6 +345,16 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match) } if (reldepObject_Check(match)) { DnfReldep *reldep = reldepFromPyObject(match); + + /* A reldep cannot be used across sack objects. If there is an attempt + * to do so, the underlying libsolv structures are incomplete and a SEGFAULT is + * likely to occur. */ + + if (query->getSack() != reldep->getSack()) { + PyErr_SetString(HyExc_Query, "Direct dependency lookups must originate from the same sack."); + return 0; + } + if (cmp_type != HY_EQ || query->addFilter(keyname, reldep)) return raise_bad_filter(); return 1; From d7723d4bfc623ffc765bac35d6dbc431577b2a7a Mon Sep 17 00:00:00 2001 From: Kyle Walker Date: Mon, 24 Oct 2022 11:07:20 -0400 Subject: [PATCH 2/2] Hawkey tests: Make the Query test per-sack Following "query-py: Ensure reldep is from the same sack", it is necessary to make Reldep use per-sack. This commit alters the Query tests to create per-sack Query objects. Signed-off-by: Kyle Walker --- python/hawkey/tests/tests/test_query.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/python/hawkey/tests/tests/test_query.py b/python/hawkey/tests/tests/test_query.py index 925584c409..c315be2649 100644 --- a/python/hawkey/tests/tests/test_query.py +++ b/python/hawkey/tests/tests/test_query.py @@ -403,13 +403,21 @@ def setUp(self): self.sack3.load_test_repo("test_ppc", "ppc.repo") def test_provides_all_arch_query(self): - ppc_pkgs = hawkey.Query(self.sack1) - self.assertGreater(len(ppc_pkgs), 0) - pkg1 = ppc_pkgs[0] + # Reldep objects are per-sack, queries across are disallowed. So + # it is necessary to create 3 queries below. + # + # See "query-py: Ensure reldep is from the same sack" for details + ppc_pkgs_1 = hawkey.Query(self.sack1) + ppc_pkgs_2 = hawkey.Query(self.sack2) + ppc_pkgs_3 = hawkey.Query(self.sack3) + self.assertGreater(len(ppc_pkgs_1), 0) + pkg1 = ppc_pkgs_1[0] + pkg2 = ppc_pkgs_2[0] + pkg3 = ppc_pkgs_3[0] query_ppc = hawkey.Query(self.sack1).filter(provides=pkg1.provides[0]) - query_x86 = hawkey.Query(self.sack2).filter(provides=pkg1.provides[0]) - query_all = hawkey.Query(self.sack3).filter(provides=pkg1.provides[0]) + query_x86 = hawkey.Query(self.sack2).filter(provides=pkg2.provides[0]) + query_all = hawkey.Query(self.sack3).filter(provides=pkg3.provides[0]) self.assertEqual(len(query_ppc), 1) self.assertEqual(len(query_x86), 0)