I have one subtle issue on my RPM/POPT todo list since a longer
time: POPT's use of the ancient 32V AT&T UNIX alloca(3), a machine-,
compiler-, and system-dependent and especially non-POSIX (and hence
less portable) function whose use is even discouraged on lots of Unix
platforms.

POPT even uses it in a IMHO unecessary way to allocate temporary
structures on the stack:

     poptDone done = alloca(sizeof(*done));

This can be just replaced by the following and let the compiler do
mostly all the work already under compile-time:

     struct poptDone_s done_buf;
     poptDone done = &done_buf;

The following patch completely kicks out all alloca(3) usages from POPT.
Either through the above replacement, or by not requiring a temporary
buffer at all (by passing length argument to internal findOption()
function) or in the worst cases by replacing with the POSIX malloc(3)
and calloc(3) functions.

I carefully performed the replacements, reviewed them individually and
the POPT "make check" still works, of course.

Any objections?
                                       Ralf S. Engelschall
                                       [EMAIL PROTECTED]
                                       www.engelschall.com

Index: configure.ac
===================================================================
RCS file: /v/rpm/cvs/popt/configure.ac,v
retrieving revision 1.15
diff -u -d -u -d -r1.15 configure.ac
--- configure.ac        14 Jun 2007 06:42:07 -0000      1.15
+++ configure.ac        14 Jun 2007 11:38:45 -0000
@@ -67,7 +67,7 @@
 fi
 AC_SUBST(MARK64)

-AC_CHECK_HEADERS(alloca.h float.h libintl.h mcheck.h unistd.h)
+AC_CHECK_HEADERS(float.h libintl.h mcheck.h unistd.h)

 # For some systems we know that we have ld_version scripts.
 # Use it then as default.
Index: findme.c
===================================================================
RCS file: /v/rpm/cvs/popt/findme.c,v
retrieving revision 1.16
diff -u -d -u -d -r1.16 findme.c
--- findme.c    14 Jun 2007 08:22:43 -0000      1.16
+++ findme.c    14 Jun 2007 11:38:45 -0000
@@ -12,9 +12,9 @@
 const char * POPT_findProgramPath(const char * argv0)
 {
     char * path = getenv("PATH");
-    char * pathbuf;
+    char * pathbuf = NULL;
     char * start, * chptr;
-    char * buf;
+    char * buf = NULL;

     if (argv0 == NULL) return NULL;    /* XXX can't happen */
     /* If there is a / in the argv[0], it has to be an absolute path */
@@ -23,9 +23,10 @@

     if (path == NULL) return NULL;

-    start = pathbuf = alloca(strlen(path) + 1);
+    start = pathbuf = malloc(strlen(path) + 1);
+    if (pathbuf == NULL) goto exit;
     buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
-    if (buf == NULL) return NULL;      /* XXX can't happen */
+    if (buf == NULL) goto exit;
     strcpy(pathbuf, path);

     chptr = NULL;
@@ -35,8 +36,10 @@
            *chptr = '\0';
        sprintf(buf, "%s/%s", start, argv0);

-       if (!access(buf, X_OK))
+       if (!access(buf, X_OK)) {
+           free(pathbuf);
            return buf;
+       }

        if (chptr)
            start = chptr + 1;
@@ -45,7 +48,11 @@
     } while (start && *start);
 /[EMAIL PROTECTED]@*/

-    free(buf);
+exit:
+    if (pathbuf)
+        free(pathbuf);
+    if (buf)
+        free(buf);

     return NULL;
 }
Index: popt.c
===================================================================
RCS file: /v/rpm/cvs/popt/popt.c,v
retrieving revision 1.100
diff -u -d -u -d -r1.100 popt.c
--- popt.c      14 Jun 2007 08:22:43 -0000      1.100
+++ popt.c      14 Jun 2007 11:38:45 -0000
@@ -394,8 +394,9 @@
     if (argv == NULL) return POPT_ERROR_MALLOC;

     if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
-       char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + 
sizeof("/"));
-       sprintf(s, "%s/%s", con->execPath, item->argv[0]);
+       char *s = malloc(strlen(con->execPath) + strlen(item->argv[0]) + 
sizeof("/"));
+       if (s)
+           sprintf(s, "%s/%s", con->execPath, item->argv[-1]);
        argv[argc] = s;
     } else
        argv[argc] = POPT_findProgramPath(item->argv[0]);
@@ -448,11 +449,6 @@
 #endif
 #endif

-    if (argv[0] == NULL) {
-       ec = POPT_ERROR_NOARG;
-       goto exit;
-    }
-
 #ifdef MYDEBUG
 if (_popt_debug)
     {  const char ** avp;
@@ -466,14 +462,18 @@
     rc = execvp(argv[0], (char *const *)argv);

 exit:
-    if (argv) free(argv);
+    if (argv) {
+        if (argv[0])
+            free((void *)argv[0]);
+        free(argv);
+    }
     return ec;
 }
 /[EMAIL PROTECTED] =boundswrite @*/

 /[EMAIL PROTECTED]@*/
 /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/ static const struct poptOption *
-findOption(const struct poptOption * opt, /[EMAIL PROTECTED]@*/ const char * 
longName,
+findOption(const struct poptOption * opt, /[EMAIL PROTECTED]@*/ const char * 
longName, int longNameLen,
                char shortName,
                /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/ poptCallbackType * 
callback,
                /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/ const void ** 
callbackData,
@@ -498,7 +498,7 @@
 /[EMAIL PROTECTED]@*/
            /* Recurse on included sub-tables. */
            if (arg == NULL) continue;  /* XXX program error */
-           opt2 = findOption(arg, longName, shortName, callback,
+           opt2 = findOption(arg, longName, longNameLen, shortName, callback,
                              callbackData, singleDash);
            if (opt2 == NULL) continue;
            /* Sub-table data will be inheirited if no data yet. */
@@ -512,7 +512,7 @@
            cb = opt;
        } else if (longName != NULL && opt->longName != NULL &&
                   (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
-                  !strcmp(longName, opt->longName))
+                  (!strncmp(longName, opt->longName, longNameLen) && 
strlen(opt->longName) == longNameLen))
        {
            break;
        } else if (shortName && shortName == opt->shortName) {
@@ -764,7 +764,8 @@

        /* Process next long option */
        if (!con->os->nextCharArg) {
-           char * localOptString, * optString;
+           char * optString;
+            int optStringLen;
            int thisopt;

 /[EMAIL PROTECTED]@*/
@@ -795,8 +796,7 @@
            }

            /* Make a copy we can hack at */
-           localOptString = optString =
-               strcpy(alloca(strlen(origOptString) + 1), origOptString);
+           optString = origOptString;

            if (optString[0] == '\0')
                return POPT_ERROR_BADOPT;
@@ -824,13 +824,11 @@
                /* Check for "--long=arg" option. */
                for (oe = optString; *oe && *oe != '='; oe++)
                    {};
-               if (*oe == '=') {
-                   *oe++ = '\0';
-                   /* XXX longArg is mapped back to persistent storage. */
-                   longArg = origOptString + (oe - localOptString);
-               }
+               optStringLen = oe - optString;
+               if (*oe == '=')
+                   longArg = oe + 1;

-               opt = findOption(con->options, optString, '\0', &cb, &cbData,
+               opt = findOption(con->options, optString, optStringLen, '\0', 
&cb, &cbData,
                                 singleDash);
                if (!opt && !singleDash)
                    return POPT_ERROR_BADOPT;
@@ -867,7 +865,7 @@
                continue;
            }

-           opt = findOption(con->options, NULL, *origOptString, &cb,
+           opt = findOption(con->options, NULL, 0, *origOptString, &cb,
                             &cbData, 0);
            if (!opt)
                return POPT_ERROR_BADOPT;
@@ -1140,7 +1138,8 @@
 int poptAddAlias(poptContext con, struct poptAlias alias,
                /[EMAIL PROTECTED]@*/ int flags)
 {
-    poptItem item = alloca(sizeof(*item));
+    struct poptItem_s item_buf;
+    poptItem item = &item_buf;
     memset(item, 0, sizeof(*item));
     item->option.longName = alias.longName;
     item->option.shortName = alias.shortName;
Index: poptconfig.c
===================================================================
RCS file: /v/rpm/cvs/popt/poptconfig.c,v
retrieving revision 1.27
diff -u -d -u -d -r1.27 poptconfig.c
--- poptconfig.c        25 May 2007 17:36:23 -0000      1.27
+++ poptconfig.c        14 Jun 2007 11:38:45 -0000
@@ -17,7 +17,8 @@
     size_t nameLength;
     const char * entryType;
     const char * opt;
-    poptItem item = alloca(sizeof(*item));
+    struct poptItem_s item_buf;
+    poptItem item = &item_buf;
     int i, j;

     if (con->appName == NULL)
@@ -95,8 +96,8 @@

 int poptReadConfigFile(poptContext con, const char * fn)
 {
-    const char * file, * chptr, * end;
-    char * buf;
+    char * file = NULL, * chptr, * end;
+    char * buf = NULL;
 /[EMAIL PROTECTED]@*/ char * dst;
     int fd, rc;
     off_t fileLength;
@@ -113,18 +114,20 @@
        return POPT_ERROR_ERRNO;
     }

-    file = alloca(fileLength + 1);
+    file = malloc(fileLength + 1);
     if (read(fd, (char *)file, fileLength) != fileLength) {
        rc = errno;
        (void) close(fd);
        errno = rc;
        return POPT_ERROR_ERRNO;
     }
-    if (close(fd) == -1)
+    if (close(fd) == -1) {
+       free(file);
        return POPT_ERROR_ERRNO;
+    }

 /[EMAIL PROTECTED]@*/
-    dst = buf = alloca(fileLength + 1);
+    dst = buf = malloc(fileLength + 1);

     chptr = file;
     end = (file + fileLength);
@@ -157,6 +160,9 @@
 /[EMAIL PROTECTED]@*/
 /[EMAIL PROTECTED]@*/

+    free(file);
+    free(buf);
+
     return 0;
 }

@@ -171,10 +177,11 @@
     if (rc) return rc;

     if ((home = getenv("HOME"))) {
-       fn = alloca(strlen(home) + 20);
+       fn = malloc(strlen(home) + 20);
        strcpy(fn, home);
        strcat(fn, "/.popt");
        rc = poptReadConfigFile(con, fn);
+       free(fn);
        if (rc) return rc;
     }

Index: popthelp.c
===================================================================
RCS file: /v/rpm/cvs/popt/popthelp.c,v
retrieving revision 1.56
diff -u -d -u -d -r1.56 popthelp.c
--- popthelp.c  14 Jun 2007 08:08:30 -0000      1.56
+++ popthelp.c  14 Jun 2007 11:38:45 -0000
@@ -767,11 +767,14 @@
        /[EMAIL PROTECTED] *str, *fp, fileSystem @*/
        /[EMAIL PROTECTED] maxRead(str) >= 0 @*/
 {
-    /* bufsize larger then the ascii set, lazy alloca on top level call. */
+    /* bufsize larger then the ascii set, lazy allocation on top level call. */
     size_t nb = (size_t)300;
-    char * s = (str != NULL ? str : memset(alloca(nb), 0, nb));
+    char * s = (str != NULL ? str : calloc(1, nb));
     size_t len = (size_t)0;

+    if (s == NULL)
+       return 0;
+
 /[EMAIL PROTECTED]@*/
     if (opt != NULL)
     for (; (opt->longName || opt->shortName || opt->arg); opt++) {
@@ -788,19 +791,23 @@
        fprintf(fp, " [-%s]", s);
        len = strlen(s) + sizeof(" [-]")-1;
     }
+    if (s != str)
+       free(s);
     return len;
 }

 void poptPrintUsage(poptContext con, FILE * fp, /[EMAIL PROTECTED]@*/ int 
flags)
 {
-    poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
+    struct poptDone_s done_buf;
+    poptDone done = &done_buf;
     size_t cursor;

+    memset(done, 0, sizeof(*done));
     done->nopts = 0;
     done->maxopts = 64;
     cursor = done->maxopts * sizeof(*done->opts);
 /[EMAIL PROTECTED]@*/
-    done->opts = memset(alloca(cursor), 0, cursor);
+    done->opts = calloc(1, cursor);
     /[EMAIL PROTECTED]@*/
     done->opts[done->nopts++] = (const void *) con->options;
     /[EMAIL PROTECTED]@*/
@@ -819,6 +826,7 @@
     }

     fprintf(fp, "\n");
+    free(done->opts);
 }

 void poptSetOtherOptionHelp(poptContext con, const char * text)
Index: poptparse.c
===================================================================
RCS file: /v/rpm/cvs/popt/poptparse.c,v
retrieving revision 1.22
diff -u -d -u -d -r1.22 poptparse.c
--- poptparse.c 14 Jun 2007 08:04:38 -0000      1.22
+++ poptparse.c 14 Jun 2007 11:38:45 -0000
@@ -62,10 +62,12 @@
     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
     int argc = 0;
     size_t buflen = strlen(s) + 1;
-    char * buf = memset(alloca(buflen), 0, buflen);
+    char * buf, * bufOrig = NULL;
     int rc = POPT_ERROR_MALLOC;

     if (argv == NULL) return rc;
+    buf = bufOrig = calloc(1, buflen);
+    if (buf == NULL) return rc;
     argv[argc] = buf;

     for (src = s; *src != '\0'; src++) {
@@ -116,6 +118,7 @@
     rc = poptDupArgv(argc, argv, argcPtr, argvPtr);

 exit:
+    if (bufOrig) free(bufOrig);
     if (argv) free(argv);
     return rc;
 }
Index: system.h
===================================================================
RCS file: /v/rpm/cvs/popt/system.h,v
retrieving revision 1.9
diff -u -d -u -d -r1.9 system.h
--- system.h    14 Jun 2007 08:16:01 -0000      1.9
+++ system.h    14 Jun 2007 11:38:45 -0000
@@ -39,32 +39,6 @@
 #include <libc.h>
 #endif

-#if defined(__LCLINT__)
-/[EMAIL PROTECTED] -incondefs @*/ /* LCL: missing annotation */
-/[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/
-void * alloca (size_t __size)
-       /[EMAIL PROTECTED] MaxSet(result) == (__size - 1) @*/
-       /[EMAIL PROTECTED]/;
-/[EMAIL PROTECTED] =incondefs @*/
-#endif
-
-/* AIX requires this to be the first thing in the file.  */
-#ifndef __GNUC__
-# ifdef HAVE_ALLOCA_H
-#  include <alloca.h>
-# else
-#  ifdef _AIX
-#pragma alloca
-#  else
-#   ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#   endif
-#  endif
-# endif
-#elif defined(__GNUC__) && defined(__STRICT_ANSI__)
-#define alloca __builtin_alloca
-#endif
-
 /[EMAIL PROTECTED] [EMAIL PROTECTED]/
 /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/
 char * xstrdup (const char *str)

______________________________________________________________________
POPT Library                                           http://rpm5.org
Developer Communication List                       [email protected]

Reply via email to