From 36c7e5ae5ccdc10fac5b5d42ecf9206181c941c1 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Aug 2007 06:22:19 +0300 Subject: [PATCH] Fix pattern matching in dpkg-query -l and -W. Do not segfault when the result from a 'dpkg-query -l' is bigger than the total number of current packages, and do not produce repeated results with overlapping patterns on 'dpkg-query -W'. --- ChangeLog | 10 ++++++ debian/changelog | 3 ++ src/query.c | 82 ++++++++++++++++++++++++++++++------------------ 3 files changed, 65 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87304163..cde65a76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-08-07 Guillem Jover + + * src/query.c (listpackages): Instead of allocating an additional + packages array with room for the the current amount of packages, + sort the existing one, and print the packages matching the pattern, + which fixes segfaults when the resulting array was bigger than the + current amount of packages. + (showpackages): For each package show it only once it matches any + of the patterns, so we avoid duplicated results. + 2007-08-07 Ian Jackson * man/deb-control.5: Document Breaks field. diff --git a/debian/changelog b/debian/changelog index 638ba6d8..b3b3fcb4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,9 @@ dpkg (1.14.6) UNRELEASED; urgency=low * Run the deconfiguration of each package to be deconfigured once, instead of once per each conflicting package being removed. Closes: #378003 Thanks to Ian Jackson. + * Do not segfault when the result from a 'dpkg-query -l' is bigger than + the total number of current packages, and do not produce repeated + results with overlapping patterns on 'dpkg-query -W'. Closes: #428427 [ Updated scripts translations ] * French (Frédéric Bothamy, Christian Perrier). diff --git a/src/query.c b/src/query.c index 1addb082..ff8d94b7 100644 --- a/src/query.c +++ b/src/query.c @@ -183,9 +183,8 @@ Desired=Unknown/Install/Remove/Purge/Hold\n\ void listpackages(const char *const *argv) { struct pkgiterator *it; struct pkginfo *pkg; - struct pkginfo **pkgl, **pkgf; - const char *thisarg; - int np, nf, i, head, found; + struct pkginfo **pkgl; + int np, i, head; modstatdb_init(admindir,msdbrw_readonly); @@ -199,33 +198,43 @@ void listpackages(const char *const *argv) { iterpkgend(it); assert(i==np); - pkgf= m_malloc(sizeof(struct pkginfo*)*np); nf=0; + qsort(pkgl, np, sizeof(struct pkginfo*), pkglistqsortcmp); + head = 0; + if (!*argv) { for (i=0; istatus == stat_notinstalled) continue; - pkgf[nf++] = pkg; + list1package(pkg, &head, pkgl, np); } } else { - while ((thisarg= *argv++)) { - found= 0; - for (i=0; iname,0)) continue; - pkgf[nf++] = pkg; found++; + int argc, ip, *found; + + for (argc = 0; argv[argc]; argc++); + found = m_malloc(sizeof(int) * argc); + memset(found, 0, sizeof(int) * argc); + + for (i = 0; i < np; i++) { + pkg = pkgl[i]; + for (ip = 0; ip < argc; ip++) { + if (!fnmatch(argv[ip], pkg->name, 0)) { + list1package(pkg, &head, pkgl, np); + found[ip]++; + break; + } } - if (!found) { - fprintf(stderr,_("No packages found matching %s.\n"),thisarg); - nerrs++; + } + + /* FIXME: we might get non-matching messages for sub-patterns specified + * after their super-patterns, due to us skipping on first match. */ + for (ip = 0; ip < argc; ip++) { + if (!found[ip]) { + fprintf(stderr, _("No packages found matching %s.\n"), argv[ip]); + nerrs++; } } } - qsort(pkgf,nf,sizeof(struct pkginfo*),pkglistqsortcmp); - head=0; - for (i=0; iname,0)) continue; - show1package(fmt,pkg); found++; + int argc, ip, *found; + + for (argc = 0; argv[argc]; argc++); + found = m_malloc(sizeof(int) * argc); + memset(found, 0, sizeof(int) * argc); + + for (i = 0; i < np; i++) { + pkg = pkgl[i]; + for (ip = 0; ip < argc; ip++) { + if (!fnmatch(argv[ip], pkg->name, 0)) { + show1package(fmt, pkg); + found[ip]++; + break; + } } - if (!found) { - fprintf(stderr,_("No packages found matching %s.\n"),thisarg); - nerrs++; + } + + /* FIXME: we might get non-matching messages for sub-patterns specified + * after their super-patterns, due to us skipping on first match. */ + for (ip = 0; ip < argc; ip++) { + if (!found[ip]) { + fprintf(stderr, _("No packages found matching %s.\n"), argv[ip]); + nerrs++; } } } + if (ferror(stdout)) werr("stdout"); if (ferror(stderr)) werr("stderr"); freeformat(fmt); -- 2.39.5