summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-03-10 17:51:58 +0100
committerThomas Haller <thaller@redhat.com>2023-03-21 15:58:38 +0100
commit46703557fb98836532fe372b657dc02d0560e8df (patch)
tree32ed32321bc55223730b9490cc7847329529fb8d
parent037b0a2b2a904eb1c4922ef982586f70bbb4b423 (diff)
glib-aux/prioq: ensure to clear "idx" when removing item from NMPrioq
NMPrioq is copied from systemd's "prioq.c". It uses the index pointer to find elements in the heap directly. However, it's not very careful about clearing or maintaining the index pointer if the element is not in the queue. Like, find_item() accepts a bogus index and only finds the data if the data and the index matches. That seems error prone. In the first step, when we remove an item from the queue, ensure to reset the index to NM_PRIOQ_IDX_NULL.
-rw-r--r--src/libnm-glib-aux/nm-prioq.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/libnm-glib-aux/nm-prioq.c b/src/libnm-glib-aux/nm-prioq.c
index f548f60089..f5bc606854 100644
--- a/src/libnm-glib-aux/nm-prioq.c
+++ b/src/libnm-glib-aux/nm-prioq.c
@@ -100,6 +100,13 @@ nm_prioq_destroy(NMPrioq *q)
_nm_assert_q(q);
+ while (q->_priv.n_items > 0) {
+ PrioqItem *i = &q->_priv.items[--q->_priv.n_items];
+
+ if (i->idx)
+ *i->idx = NM_PRIOQ_IDX_NULL;
+ }
+
free(q->_priv.items);
q->_priv.compare_func = NULL;
}
@@ -238,11 +245,15 @@ remove_item(NMPrioq *q, PrioqItem *i)
_nm_assert_item(q, i);
- l = &q->_priv.items[q->_priv.n_items - 1u];
+ if (i->idx)
+ *i->idx = NM_PRIOQ_IDX_NULL;
+
+ q->_priv.n_items--;
+
+ l = &q->_priv.items[q->_priv.n_items];
if (i == l) {
- /* Last entry, let's just remove it */
- q->_priv.n_items--;
+ /* Last entry, nothing to do. */
return;
}
@@ -252,9 +263,9 @@ remove_item(NMPrioq *q, PrioqItem *i)
k = i - q->_priv.items;
*i = *l;
+
if (i->idx)
*i->idx = k;
- q->_priv.n_items--;
k = shuffle_down(q, k);
shuffle_up(q, k);