X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fxvasprintf.c;h=7a4029e7908aa9ab9fc8493e5335266209beba2e;hb=7ef6c64e210ac0979d7e8ac69bc5b5208c2405ab;hp=beea45ac13c0dbf8e9fc5c5369b15457f6b9e2b1;hpb=6abae3924eb57e5eea340d55c10c7eab507b556c;p=gnulib.git diff --git a/lib/xvasprintf.c b/lib/xvasprintf.c index beea45ac1..7a4029e79 100644 --- a/lib/xvasprintf.c +++ b/lib/xvasprintf.c @@ -1,41 +1,108 @@ /* vasprintf and asprintf with out-of-memory checking. - Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2004, 2006-2014 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + 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 - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include /* Specification. */ #include "xvasprintf.h" #include +#include +#include +#include -#include "vasprintf.h" #include "xalloc.h" +/* Checked size_t computations. */ +#include "xsize.h" + +static char * +xstrcat (size_t argcount, va_list args) +{ + char *result; + va_list ap; + size_t totalsize; + size_t i; + char *p; + + /* Determine the total size. */ + totalsize = 0; + va_copy (ap, args); + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (ap, const char *); + totalsize = xsum (totalsize, strlen (next)); + } + va_end (ap); + + /* Test for overflow in the summing pass above or in (totalsize + 1) below. + Also, don't return a string longer than INT_MAX, for consistency with + vasprintf(). */ + if (totalsize == SIZE_MAX || totalsize > INT_MAX) + { + errno = EOVERFLOW; + return NULL; + } + + /* Allocate and fill the result string. */ + result = XNMALLOC (totalsize + 1, char); + p = result; + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (args, const char *); + size_t len = strlen (next); + memcpy (p, next, len); + p += len; + } + *p = '\0'; + + return result; +} + char * xvasprintf (const char *format, va_list args) { char *result; + /* Recognize the special case format = "%s...%s". It is a frequently used + idiom for string concatenation and needs to be fast. We don't want to + have a separate function xstrcat() for this purpose. */ + { + size_t argcount = 0; + const char *f; + + for (f = format;;) + { + if (*f == '\0') + /* Recognized the special case of string concatenation. */ + return xstrcat (argcount, args); + if (*f != '%') + break; + f++; + if (*f != 's') + break; + f++; + argcount++; + } + } + if (vasprintf (&result, format, args) < 0) { if (errno == ENOMEM) - xalloc_die (); + xalloc_die (); return NULL; }