multiarch: dpkg-query segfaults
Hi Guillem and Raphaël,
Being the adventurous sort, I tried building and installing dpkg from
guillem/pu/multiarch/master. "dpkg" seems to work ok, but dpkg-query
is broken (it always segfaults).
Ok, back to dpkg/sid (thanks for the maintainer scripts that make
switching between very easy). Luckily the segfault is reproducible
without installing a new dpkg version:
$ build-tree/src/dpkg-query -l dpkg
Segmentation fault
Also reproducible with raphael/pu/multiarch/full. Bisects to 8c57a40d
(libdpkg: update package sorting logic to take into account the
architecture), which didn't take into account that some callers of
pkg_sorter_by_name leave pkg->installed and pkg->available blank (the
juicy stuff for them seems to be in pkg->set).
The diff below [1] works around it.
We get another segfault in the same spirit (same reproduction recipe)
in 26516da (dpkg-query: Update commands to accept package specifiers
as arguments). It is due to this code:
| for (i = 0; i < array.n_pkgs; i++) {
| pkg = array.pkgs[i];
| for (ip = 0; ip < argc; ip++) {
| - if (!fnmatch(argv[ip], pkg->set->name, 0)) {
| + if (pkg_spec_match_pkg(&ps[ip], pkg, &pkg->installed)) {
"dpkg-query -l dpkg:amd64" seems to work fine.
I guess that is because when the commandline parameter does not
include an architecture specifier, pkgs[i]->installed.arch is examined
to check if it's a native package, and since arch is NULL, segfault.
So the diff below [1] works around that, too.
Another oddity:
$ dpkg-query --search -- /lib/x86_64-linux-gnu/libc.so.6
strcpy: /lib/x86_64-linux-gnu/libc.so.6
Bisects to 3c971ae (dpkg-query: Update --list and --show to output
package specifiers)
Hints?
Jonathan
[1]
lib/dpkg/pkg-spec.c | 4 ++++
lib/dpkg/pkg.c | 7 +++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/lib/dpkg/pkg-spec.c b/lib/dpkg/pkg-spec.c
index 2859bad8..ee119c78 100644
--- a/lib/dpkg/pkg-spec.c
+++ b/lib/dpkg/pkg-spec.c
@@ -141,6 +141,10 @@ pkg_spec_parse(struct pkg_spec *ps, const char *str)
static bool
pkg_spec_match_arch(struct pkg_spec *ps, const struct dpkg_arch *arch)
{
+ /* These should just never match. */
+ if (!arch)
+ return false;
+
if (ps->arch_is_pattern)
return (fnmatch(ps->arch->name, arch->name, 0) == 0);
else if (ps->arch->type != arch_none) /* !arch_is_pattern */
diff --git a/lib/dpkg/pkg.c b/lib/dpkg/pkg.c
index 2dc00d9b..1495c1d0 100644
--- a/lib/dpkg/pkg.c
+++ b/lib/dpkg/pkg.c
@@ -136,8 +136,8 @@ pkg_sorter_by_name(const void *a, const void *b)
{
const struct pkginfo *pa = *(const struct pkginfo **)a;
const struct pkginfo *pb = *(const struct pkginfo **)b;
- const char *arch_a = pa->installed.arch->name;
- const char *arch_b = pb->installed.arch->name;
+ const char *arch_a;
+ const char *arch_b;
int res;
res = strcmp(pa->set->name, pb->set->name);
@@ -155,5 +155,8 @@ pkg_sorter_by_name(const void *a, const void *b)
pb->installed.arch->type == arch_native)
arch_b = "";
+ arch_b = pb->installed.arch->name;
+ arch_a = pa->installed.arch->name;
+
return strcmp(arch_a, arch_b);
}
--
1.7.8.rc3
Reply to: