1 /* vasprintf and asprintf with out-of-memory checking. 2 Copyright (C) 1999, 2002-2004, 2006 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with this program; if not, write to the Free Software Foundation, 16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18 #include <config.h> 19 20 /* Specification. */ 21 #include "xvasprintf.h" 22 23 #include <errno.h> 24 #include <limits.h> 25 #include <string.h> 26 27 #include "vasprintf.h" 28 #include "xalloc.h" 29 30 /* Checked size_t computations. */ 31 #include "xsize.h" 32 33 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ 34 #ifndef EOVERFLOW 35 # define EOVERFLOW E2BIG 36 #endif 37 38 static inline char * 39 xstrcat (size_t argcount, va_list args) 40 { 41 char *result; 42 va_list ap; 43 size_t totalsize; 44 size_t i; 45 char *p; 46 47 /* Determine the total size. */ 48 totalsize = 0; 49 va_copy (ap, args); 50 for (i = argcount; i > 0; i--) 51 { 52 const char *next = va_arg (ap, const char *); 53 totalsize = xsum (totalsize, strlen (next)); 54 } 55 va_end (ap); 56 57 /* Test for overflow in the summing pass above or in (totalsize + 1) below. 58 Also, don't return a string longer than INT_MAX, for consistency with 59 vasprintf(). */ 60 if (totalsize == SIZE_MAX || totalsize > INT_MAX) 61 { 62 errno = EOVERFLOW; 63 return NULL; 64 } 65 66 /* Allocate and fill the result string. */ 67 result = (char *) xmalloc (totalsize + 1); 68 p = result; 69 for (i = argcount; i > 0; i--) 70 { 71 const char *next = va_arg (args, const char *); 72 size_t len = strlen (next); 73 memcpy (p, next, len); 74 p += len; 75 } 76 *p = '\0'; 77 78 return result; 79 } 80 81 char * 82 xvasprintf (const char *format, va_list args) 83 { 84 char *result; 85 86 /* Recognize the special case format = "%s...%s". It is a frequently used 87 idiom for string concatenation and needs to be fast. We don't want to 88 have a separate function xstrcat() for this purpose. */ 89 { 90 size_t argcount = 0; 91 const char *f; 92 93 for (f = format;;) 94 { 95 if (*f == '\0') 96 /* Recognized the special case of string concatenation. */ 97 return xstrcat (argcount, args); 98 if (*f != '%') 99 break; 100 f++; 101 if (*f != 's') 102 break; 103 f++; 104 argcount++; 105 } 106 } 107 108 if (vasprintf (&result, format, args) < 0) 109 { 110 if (errno == ENOMEM) 111 xalloc_die (); 112 return NULL; 113 } 114 115 return result; 116 } 117