1 /* 2 * concat() - allocate memory and safely concatenate strings in portable C 3 * (and C++ if you like). 4 * 5 * This code deals gracefully with potential integer overflows (perhaps when 6 * input strings are maliciously long), as well as with input strings changing 7 * from under it (perhaps because of misbehavior of another thread). It does 8 * not depend on non-portable functions such as snprintf() and asprintf(). 9 * 10 * Written by Solar Designer <solar at openwall.com> and placed in the 11 * public domain. 12 */ 13 14 #include <string.h> 15 #include <stdarg.h> 16 #include <stdlib.h> 17 #include <limits.h> 18 #include "concat.h" 19 20 char *concat(const char *s1, ...) 21 { 22 va_list args; 23 const char *s; 24 char *p, *result; 25 size_t l, m, n; 26 27 m = n = strlen(s1); 28 va_start(args, s1); 29 while ((s = va_arg(args, char *))) { 30 l = strlen(s); 31 if ((m += l) < l) 32 break; 33 } 34 va_end(args); 35 if (s || m >= INT_MAX) 36 return NULL; 37 38 result = (char *)malloc(m + 1); 39 if (!result) 40 return NULL; 41 42 memcpy(p = result, s1, n); 43 p += n; 44 va_start(args, s1); 45 while ((s = va_arg(args, char *))) { 46 l = strlen(s); 47 if ((n += l) < l || n > m) 48 break; 49 memcpy(p, s, l); 50 p += l; 51 } 52 va_end(args); 53 if (s || m != n || p != result + n) { 54 free(result); 55 return NULL; 56 } 57 58 *p = 0; 59 return result; 60 } 61 62 #ifdef TEST 63 #include <stdio.h> 64 65 int main(int argc, char **argv) 66 { 67 puts(concat(argv[0], argv[1], argv[2], argv[3], NULL)); 68 return 0; 69 } 70 #endif 71