diff options
author | Boris Staletic <boris.staletic@protonmail.com> | 2024-03-28 19:08:00 +0100 |
---|---|---|
committer | Fabian Groffen <grobian@gentoo.org> | 2024-03-29 11:57:17 +0100 |
commit | 268c2076b5276fbce37df3f751619646c4b8d7a4 (patch) | |
tree | 027885f85a13b0f1d75347f95ff330ab4b5d8c8e | |
parent | qmerge: add reminder for myself (diff) | |
download | portage-utils-268c2076b5276fbce37df3f751619646c4b8d7a4.tar.gz portage-utils-268c2076b5276fbce37df3f751619646c4b8d7a4.tar.bz2 portage-utils-268c2076b5276fbce37df3f751619646c4b8d7a4.zip |
qlop: Properly handle atom_compar_cb when called from qsort
`qsort` passes pointers to elements ("iterators" in C++ lingo) to the
callback, not elements directly.
Hence `l` and `r` in `atom_compar_cb` actually receives `depend_atom**`,
but only when called from `qsort`. The other two call sites
(`tree_pkg_compar` and `pkg_sort_cb`) actually apssed `depend_atom*`.
This leads to type casting confusion and undefined behaviour for any
invocation of `qlop -p`.
First discovered by SEGFAULT-ing with the following invocation:
qlop -p `cat /var/lib/portage/world`
Valgrind and ASAN made triggering the SEGFAULT easier - any invocation
with two or more atoms triggered a NULL dereference.
This commit addresses the above problem:
1. Expect that `atom_compar_cb` is actually called with two
`depend_atom**`.
2. Make `tree_pkg_compar` and `pkg_sort_cb` comply with the above
change, by passing `&al` and `&ar`, instead of `al` and `ar`.
Signed-off-by: Fabian Groffen <grobian@gentoo.org>
-rw-r--r-- | libq/atom.c | 4 | ||||
-rw-r--r-- | libq/tree.c | 2 | ||||
-rw-r--r-- | qlop.c | 2 |
3 files changed, 4 insertions, 4 deletions
diff --git a/libq/atom.c b/libq/atom.c index b1a150a..3cc2100 100644 --- a/libq/atom.c +++ b/libq/atom.c @@ -1242,8 +1242,8 @@ atom_format(const char *format, const depend_atom *atom) inline int atom_compar_cb(const void *l, const void *r) { - const depend_atom *al = l; - const depend_atom *ar = r; + const depend_atom *al = *(const depend_atom**)l; + const depend_atom *ar = *(const depend_atom**)r; switch (atom_compare(al, ar)) { case EQUAL: return 0; diff --git a/libq/tree.c b/libq/tree.c index 4678634..335ac79 100644 --- a/libq/tree.c +++ b/libq/tree.c @@ -463,7 +463,7 @@ tree_pkg_compar(const void *l, const void *r) depend_atom *al = tree_get_atom(pl, false); depend_atom *ar = tree_get_atom(pr, false); - return atom_compar_cb(al, ar); + return atom_compar_cb(&al, &ar); } static tree_pkg_ctx * @@ -309,7 +309,7 @@ pkg_sort_cb(const void *l, const void *r) depend_atom *al = pl->atom; depend_atom *ar = pr->atom; - return atom_compar_cb(al, ar); + return atom_compar_cb(&al, &ar); } /* The format of the sync log has changed over time. |