]> err.no Git - dpkg/commitdiff
Fix pattern matching in dpkg-query -l and -W.
authorGuillem Jover <guillem@debian.org>
Tue, 7 Aug 2007 03:22:19 +0000 (06:22 +0300)
committerGuillem Jover <guillem@debian.org>
Tue, 7 Aug 2007 03:22:34 +0000 (06:22 +0300)
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
debian/changelog
src/query.c

index 87304163eeac2cc80fe2f520466949fe94d3cffe..cde65a76cd59db5c1e85653c1acd35cca7800fa8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-08-07  Guillem Jover  <guillem@debian.org>
+
+       * 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  <iwj@ubuntu.com>
 
        * man/deb-control.5: Document Breaks field.
index 638ba6d8dd73b98085314c6d5d811ae6a0a2093d..b3b3fcb499541acb3d8e26f4801d27f6fad412ad 100644 (file)
@@ -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).
index 1addb0826bd2d04f96f6f709cf8479c497fa286e..ff8d94b75aae7422bb447ed4dd89ceef10048697 100644 (file)
@@ -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; i<np; i++) {
       pkg= pkgl[i];
       if (pkg->status == stat_notinstalled) continue;
-      pkgf[nf++] = pkg;
+      list1package(pkg, &head, pkgl, np);
     }
   } else {
-    while ((thisarg= *argv++)) {
-      found= 0;
-      for (i=0; i<np; i++) {
-        pkg= pkgl[i];
-        if (fnmatch(thisarg,pkg->name,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; i<nf; i++)
-    list1package(pkgf[i],&head,pkgf,nf);
-
   if (ferror(stdout)) werr("stdout");
   if (ferror(stderr)) werr("stderr");  
   modstatdb_shutdown();
@@ -412,8 +421,7 @@ void showpackages(const char *const *argv) {
   struct pkgiterator *it;
   struct pkginfo *pkg;
   struct pkginfo **pkgl;
-  const char *thisarg;
-  int np, i, found;
+  int np, i;
   struct lstitem* fmt = parseformat(showformat);
 
   if (!fmt) {
@@ -442,19 +450,33 @@ void showpackages(const char *const *argv) {
       show1package(fmt,pkg);
     }
   } else {
-    while ((thisarg= *argv++)) {
-      found= 0;
-      for (i=0; i<np; i++) {
-        pkg= pkgl[i];
-        if (fnmatch(thisarg,pkg->name,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);