sys/vfs/hammer2: Fix multiple "radii" -> "radix"
[dragonfly.git] / contrib / pam_passwdqc / concat.c
blobde1f75dcbb519345447ad5863ba5195b761ec00d
1 /*
2 * concat() - allocate memory and safely concatenate strings in portable C
3 * (and C++ if you like).
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().
10 * Written by Solar Designer <solar at openwall.com> and placed in the
11 * public domain.
14 #include <string.h>
15 #include <stdarg.h>
16 #include <stdlib.h>
17 #include <limits.h>
18 #include "concat.h"
20 char *concat(const char *s1, ...)
22 va_list args;
23 const char *s;
24 char *p, *result;
25 size_t l, m, n;
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;
34 va_end(args);
35 if (s || m >= INT_MAX)
36 return NULL;
38 result = (char *)malloc(m + 1);
39 if (!result)
40 return NULL;
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;
52 va_end(args);
53 if (s || m != n || p != result + n) {
54 free(result);
55 return NULL;
58 *p = 0;
59 return result;
62 #ifdef TEST
63 #include <stdio.h>
65 int main(int argc, char **argv)
67 puts(concat(argv[0], argv[1], argv[2], argv[3], NULL));
68 return 0;
70 #endif