From 594560870c416d0133b08a64e0632a53a6217f71 Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Mon, 20 Jan 2020 09:58:03 +0100 Subject: [PATCH] Fix filtering packages by advisory (RhBug:1770125) Currently the filter does not work well in situation when more versions and architectures of advisory packages are available. Let's have package gjs-1.56.2-6.fc30.x86_64 and two advisories related to gjs package: FEDORA-2019-f4eb34cf4c gjs-1.56.2-1.fc30.src gjs-1.56.2-1.fc30.x86_64 FEDORA-2019-57b5902ed1 gjs-1.56.2-6.fc30.src gjs-1.56.2-6.fc30.x86_64 In this case the FEDORA-2019-57b5902ed1 advisory is not matched for gjs-1.56.2-6.fc30.x86_64 package (considering >= operator as in 'dnf update --bugfix') because only the package of `src` architecture as been checked. The checking of other versions/architectures was missing. https://bugzilla.redhat.com/show_bug.cgi?id=1770125 --- libdnf/sack/query.cpp | 63 +++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp index 6e9e4715f..122a50df6 100644 --- a/libdnf/sack/query.cpp +++ b/libdnf/sack/query.cpp @@ -518,9 +518,9 @@ advisoryPkgCompareSolvable(const AdvisoryPkg &first, const Solvable &s) { if (first.getName() != s.name) return first.getName() < s.name; - if (first.getEVR() != s.evr) - return first.getEVR() < s.evr; - return first.getArch() < s.arch; + if (first.getArch() != s.arch) + return first.getArch() < s.arch; + return first.getEVR() < s.evr; } static bool @@ -1607,13 +1607,12 @@ Query::Impl::filterLocation(const Filter & f, Map *m) /** * @brief Reduce query to security filters. It reflect following compare types: HY_EQ, HY_GT, HY_LT. -* In case HY_GT or HY_LT, it first find all advisory packages that EQ to packages in result. -* Then it adds packages from Result to Map *m if Name and Arch is EQ, and EVR comparison is -* according to one of selected compare type (HY_EQ, HY_GT, HY_LT). * -* @param f p_f:... -* @param m p_m:... -* @param keyname p_keyname:... +* @param f: Filter that should be applied on advisories +* @param m: Map of query results complying the filter +* @param keyname: how are the advisories matched. HY_PKG_ADVISORY, HY_PKG_ADVISORY_BUG, +* HY_PKG_ADVISORY_CVE, HY_PKG_ADVISORY_TYPE and HY_PKG_ADVISORY_SEVERITY +* are supported */ void Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname) @@ -1668,7 +1667,6 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname) // convert nevras (from DnfAdvisoryPkg) to pool ids Id id = -1; int cmp_type = f.getCmpType(); - bool cmpTypeGreaterOrLower = cmp_type & HY_GT || cmp_type & HY_LT; while (true) { if (pkgs.size() == 0) break; @@ -1676,40 +1674,23 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname) if (id == -1) break; Solvable* s = pool_id2solvable(pool, id); - auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvable); - if (low != pkgs.end() && low->nevraEQ(s)) { - if (cmpTypeGreaterOrLower) { - pkgsSecondRun.push_back(*low); - } else { + if (cmp_type == HY_EQ) { + auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvable); + if (low != pkgs.end() && low->nevraEQ(s)) { MAPSET(m, id); } - } - } - if (!cmpTypeGreaterOrLower) { - return; - } - std::sort(pkgsSecondRun.begin(), pkgsSecondRun.end(), advisoryPkgSort); - id = -1; - while (true) { - if (pkgsSecondRun.size() == 0) - break; - id = resultPset->next(id); - if (id == -1) - break; - Solvable* s = pool_id2solvable(pool, id); - auto low = std::lower_bound(pkgsSecondRun.begin(), pkgsSecondRun.end(), *s, - advisoryPkgCompareSolvableNameArch); - while (low != pkgsSecondRun.end() && low->getName() == s->name && - low->getArch() == s->arch) { - - int cmp = pool_evrcmp(pool, s->evr, low->getEVR(), EVRCMP_COMPARE); - if ((cmp > 0 && cmp_type & HY_GT) || - (cmp < 0 && cmp_type & HY_LT) || - (cmp == 0 && cmp_type & HY_EQ)) { - MAPSET(m, id); - break; + } else { + auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvableNameArch); + while (low != pkgs.end() && low->getName() == s->name && low->getArch() == s->arch) { + int cmp = pool_evrcmp(pool, s->evr, low->getEVR(), EVRCMP_COMPARE); + if ((cmp > 0 && cmp_type & HY_GT) || + (cmp < 0 && cmp_type & HY_LT) || + (cmp == 0 && cmp_type & HY_EQ)) { + MAPSET(m, id); + break; + } + ++low; } - ++low; } } }