Rewrite sprintf_alloc.
authorgraham.gower@gmail.com <graham.gower@gmail.com@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Fri, 19 Nov 2010 03:55:52 +0000 (03:55 +0000)
committergraham.gower@gmail.com <graham.gower@gmail.com@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Fri, 19 Nov 2010 03:55:52 +0000 (03:55 +0000)
The example in printf(3) that this was taken from should not be used as
it ignores negative return codes from vsnprintf, instead allocating more
memory. Given an error from vsnprintf, this would loop until the process'
virtual memory is exhausted.

So we just exit in the event of a problem instead.

git-svn-id: http://opkg.googlecode.com/svn/trunk@581 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358

libopkg/sprintf_alloc.c
libopkg/sprintf_alloc.h

index 08c56bfe11b2b041f75ea2837132fc6e6d8ef582..e2513ecee5fda05c59861f6d08d0205d71270faa 100644 (file)
@@ -1,8 +1,6 @@
 /* sprintf_alloc.c -- like sprintf with memory allocation
 
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
+   Copyright (C) 2010 Ubiq Technologies <graham.gower@gmail.com>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "sprintf_alloc.h"
 #include "libbb/libbb.h"
 
-int sprintf_alloc(char **str, const char *fmt, ...)
+void
+sprintf_alloc(char **str, const char *fmt, ...)
 {
        va_list ap;
        int n;
-       unsigned size = 100;
-
-       if (!str) {
-               opkg_msg(ERROR, "Internal error: str=NULL.\n");
-               return -1;
-       }
-       if (!fmt) {
-               opkg_msg(ERROR, "Internal error: fmt=NULL.\n");
-               return -1;
-       }
-
-       /* On x86_64 systems, any strings over 100 were segfaulting.
-          It seems that the ap needs to be reinitalized before every
-          use of the v*printf() functions. I pulled the functionality out
-          of vsprintf_alloc and combined it all here instead.
-       */
-
-
-       /* ripped more or less straight out of PRINTF(3) */
+       unsigned int size = 1;
 
        *str = xcalloc(1, size);
 
-       while (1) {
+       for (;;) {
                va_start(ap, fmt);
                n = vsnprintf (*str, size, fmt, ap);
                va_end(ap);
-               /* If that worked, return the size. */
-               if (n > -1 && n < size)
-                       return n;
-               /* Else try again with more space. */
-               if (n > -1)    /* glibc 2.1 */
-                       size = n+1; /* precisely what is needed */
-               else           /* glibc 2.0 */
-                       size *= 2;  /* twice the old size */
+
+               if (n < 0) {
+                       fprintf(stderr, "%s: encountered an output or encoding"
+                                       " error during vsnprintf.\n",
+                                       __FUNCTION__);
+                       exit(EXIT_FAILURE);
+               }
+
+               if (n < size)
+                       break;
+
+               /* Truncated, try again with more space. */
+               size = n+1;
                *str = xrealloc(*str, size);
        }
-
-       return -1; /* Just to be correct - it probably won't get here */
 }
index 3d68d69a3b8e1337080c8c549d5ca0329e81f607..bcf42a4f1ce5803e7c6f3f3a6f2481c8a66b0400 100644 (file)
@@ -18,6 +18,6 @@
 #ifndef SPRINTF_ALLOC_H
 #define SPRINTF_ALLOC_H
 
-int sprintf_alloc(char **str, const char *fmt, ...);
+void sprintf_alloc(char **str, const char *fmt, ...);
 
 #endif