Package: libpopt-dev
Version: 1.7-5
Severity: important
Tags: patch

Hi,

it seems like poptStuffArgs() hasn't been tested very thoroughly.  If
used twice with the same context, it will invariably cause memory
corruption and possibly memory leaks or a crash.

The proper fix is to change the allocation of leftOvers so it adapts
to the input on the fly instead of trying to pre-allocate it in one
go.

Patch attached.

Cheers,
Richard

-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.11-1-686
Locale: LANG=sv_SE, LC_CTYPE=sv_SE (charmap=ISO-8859-1)

Versions of packages libpopt-dev depends on:
ii  libc6-dev [libc-dev]        2.3.2.ds1-22 GNU C Library: Development Librari
ii  libpopt0                    1.7-5        lib for parsing cmdline parameters

libpopt-dev recommends no packages.

-- no debconf information
--- popt.c
+++ popt.c
@@ -168,7 +168,8 @@
     if (!(flags & POPT_CONTEXT_KEEP_FIRST))
        con->os->next = 1;                      /* skip argv[0] */
 
-    con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
+    con->allocLeftovers = argc + 1;
+    con->leftovers = calloc( con->allocLeftovers, sizeof(*con->leftovers) );
     /[EMAIL PROTECTED] [EMAIL PROTECTED]/      /* FIX: W2DO? */
     con->options = options;
     /[EMAIL PROTECTED] [EMAIL PROTECTED]/
@@ -742,7 +743,19 @@
                    return 0;
                }
                if (con->leftovers != NULL)     /* XXX can't happen */
-                   con->leftovers[con->numLeftovers++] = origOptString;
+                   /* One might think we can never overflow the leftovers
+                      array.  Actually, that's true, as long as you don't
+                      use poptStuffArgs()... */
+                   if ((con->numLeftovers + 1) >= (con->allocLeftovers)) {
+                       con->allocLeftovers += 10;
+                       con->leftovers =
+                           realloc(con->leftovers,
+                                   sizeof(*con->leftovers) * 
con->allocLeftovers);
+                   }
+                   con->leftovers[con->numLeftovers++]
+                       = xstrdup(origOptString); /* so a free of a stuffed
+                                                    argv doesn't give us a
+                                                    dangling pointer */
                continue;
            }
 
@@ -1076,7 +1089,11 @@
     }
     con->execs = _free(con->execs);
 
+    for (i = 0; i < con->numLeftovers; i++) {
+       con->leftovers[i] = _free(&con->leftovers[i]);
+    }
     con->leftovers = _free(con->leftovers);
+
     con->finalArgv = _free(con->finalArgv);
     con->appName = _free(con->appName);
     con->otherHelp = _free(con->otherHelp);
--- poptint.h
+++ poptint.h
@@ -65,6 +65,7 @@
 /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/
     const char ** leftovers;
     int numLeftovers;
+    int allocLeftovers;
     int nextLeftover;
 /[EMAIL PROTECTED]@*/
     const struct poptOption * options;

Reply via email to