public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
To: git-commits@fedoraproject.org
Subject: [rpms/dnf5] f44: libdnf5: Fix dangling reference bug in is_vendor_change_allowed
Date: Fri, 04 Sep 2026 12:33:20 GMT	[thread overview]
Message-ID: <178852520091.1.16124443269040874160.rpms-dnf5-46325679b88f@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/dnf5
Branch : f44
Commit : 46325679b88fbfa16adbde8f67e0b873170c5863
Author : Petr Písař <ppisar@redhat.com>
Date   : 2026-09-04T14:33:09+02:00
Stats  : +103/-0 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/dnf5/c/46325679b88fbfa16adbde8f67e0b873170c5863?branch=f44

Log:
libdnf5: Fix dangling reference bug in is_vendor_change_allowed

---
diff --git a/0002-libdnf5-Fix-dangling-reference-bug-in-is_vendor_chan.patch b/0002-libdnf5-Fix-dangling-reference-bug-in-is_vendor_chan.patch
new file mode 100644
index 0000000..3d79fad
--- /dev/null
+++ b/0002-libdnf5-Fix-dangling-reference-bug-in-is_vendor_chan.patch
@@ -0,0 +1,101 @@
+From 9c81f4893f23c2fbe066c25f5d389ab5c349b72a Mon Sep 17 00:00:00 2001
+From: Jaroslav Rohel <jrohel@redhat.com>
+Date: Mon, 24 Aug 2026 13:54:13 +0200
+Subject: [PATCH] libdnf5: Fix dangling reference bug in
+ is_vendor_change_allowed
+
+Bug scenario:
+In VendorChangeManager::is_vendor_change_allowed(), two references are
+obtained sequentially:
+1. const auto & outgoing_vendor_mask = get_vendor_change_masks(
+   outgoing_vendor).outgoing_mask;
+2. const auto & incoming_vendor_mask = get_vendor_change_masks(
+   incoming_vendor).incoming_mask;
+
+If incoming_vendor is not cached, get_vendor_change_masks() calls
+vendor_masks.emplace_back() (vendor_masks is std::vector) which may
+reallocate the vector, invalidating the outgoing_vendor_mask reference
+from step 1.
+
+Fix:
+Replace std::vector with std::map. std::map guarantees that references
+to existing elements remain valid after inserting new elements (no
+reallocation like vector).
+Secondary benefit: O(log n) lookup instead of O(n) linear search.
+---
+ libdnf5/solv/vendor_change_manager.cpp | 16 ++++++++--------
+ libdnf5/solv/vendor_change_manager.hpp |  4 ++--
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/libdnf5/solv/vendor_change_manager.cpp b/libdnf5/solv/vendor_change_manager.cpp
+index 430760ada..7b3469623 100644
+--- a/libdnf5/solv/vendor_change_manager.cpp
++++ b/libdnf5/solv/vendor_change_manager.cpp
+@@ -195,20 +195,19 @@ bool VendorChangeManager::is_vendor_change_allowed(Solvable & outgoing, Solvable
+ 
+ const VendorChangeManager::VendorChangeMasks & VendorChangeManager::get_vendor_change_masks(Id vendor) {
+     constexpr int EXTRA_CAPACITY = 7;
+-    static const VendorChangeMasks empty_masks{.vendor = 0};
+-    VendorChangeMasks masks;
++    static const VendorChangeMasks empty_masks;
+ 
+     if (vendor == 0 || vendor_policies_def.empty()) {
+         return empty_masks;
+     }
+ 
+-    for (const auto & vendor_to_classes : vendor_masks) {
+-        if (vendor_to_classes.vendor == vendor) {
+-            return vendor_to_classes;
+-        }
++    // Check if masks for this vendor are already cached
++    if (auto it = vendor_masks.find(vendor); it != vendor_masks.end()) {
++        return it->second;
+     }
+ 
+-    masks.vendor = vendor;
++    // Create new masks for this vendor
++    VendorChangeMasks masks;
+     auto vendor_str = pool.id2str(vendor);
+     for (unsigned int class_idx = 0; class_idx < vendor_policies_def.size(); ++class_idx) {
+         const auto & vendor_class_def = vendor_policies_def[class_idx];
+@@ -240,7 +239,8 @@ const VendorChangeManager::VendorChangeMasks & VendorChangeManager::get_vendor_c
+         }
+     }
+ 
+-    return vendor_masks.emplace_back(masks);
++    // Insert into map and return reference to the inserted value
++    return vendor_masks.emplace(vendor, std::move(masks)).first->second;
+ }
+ 
+ 
+diff --git a/libdnf5/solv/vendor_change_manager.hpp b/libdnf5/solv/vendor_change_manager.hpp
+index ebe53c8ef..9d651b597 100644
+--- a/libdnf5/solv/vendor_change_manager.hpp
++++ b/libdnf5/solv/vendor_change_manager.hpp
+@@ -9,6 +9,7 @@
+ #include "libdnf5/common/sack/query_cmp.hpp"
+ 
+ #include <filesystem>
++#include <map>
+ #include <string>
+ #include <vector>
+ 
+@@ -87,14 +88,13 @@ public:
+ 
+ private:
+     struct VendorChangeMasks {
+-        Id vendor;
+         SolvMap outgoing_mask{0};
+         SolvMap incoming_mask{0};
+     };
+ 
+     const Pool & pool;
+     std::vector<VendorChangePolicy> vendor_policies_def;
+-    std::vector<VendorChangeMasks> vendor_masks;
++    std::map<Id, VendorChangeMasks> vendor_masks;
+     SolvMap incoming_vendor_bypassed_solvables{0};
+ 
+     /// Retrieve or cache masks for a specific vendor
+-- 
+2.55.0
+

diff --git a/dnf5.spec b/dnf5.spec
index 22785d0..9128be1 100644
--- a/dnf5.spec
+++ b/dnf5.spec
@@ -83,6 +83,7 @@ License:        GPL-2.0-or-later
 URL:            https://github.com/rpm-software-management/dnf5
 Source0:        %{url}/archive/%{version}/dnf5-%{version}.tar.gz
 Patch1:         0001-spec-Fix-bcond-ordering-so-plugin_systemd_inhibit-is.patch
+Patch2:         0002-libdnf5-Fix-dangling-reference-bug-in-is_vendor_chan.patch
 
 Requires:       libdnf5%{?_isa} = %{version}-%{release}
 Requires:       libdnf5-cli%{?_isa} = %{version}-%{release}
@@ -1207,6 +1208,7 @@ mkdir -p %{buildroot}%{_libdir}/libdnf5/plugins
 - Update to version 5.4.4.0
 - Correct libdnf5-cli license to "GPL-2.0-or-later AND LGPL-2.1-or-later"
 - spec: Fix bcond ordering so plugin_systemd_inhibit is enabled
+- libdnf5: Fix dangling reference bug in is_vendor_change_allowed
 
 * Wed Aug 19 2026 Petr Pisar <ppisar@redhat.com> - 5.4.3.0-2
 - Restore ABI (upstream GH#2869)

                 reply	other threads:[~2026-09-04 12:33 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178852520091.1.16124443269040874160.rpms-dnf5-46325679b88f@fedoraproject.org \
    --to=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox