concat() - allocate memory and safely concatenate strings in portable C/C++

Download concat.c (shown below).

This code is used in popa3d, passwdqc, and blists.

Back to other source code snippets and frameworks placed in the public domain.

/*
 * concat() - allocate memory and safely concatenate strings in portable C
 * (and C++ if you like).
 *
 * This code deals gracefully with potential integer overflows (perhaps when
 * input strings are maliciously long), as well as with input strings changing
 * from under it (perhaps because of misbehavior of another thread).  It does
 * not depend on non-portable functions such as snprintf() and asprintf().
 *
 * Written by Solar Designer <solar at openwall.com> and placed in the
 * public domain.
 *
 * Originally written for and currently maintained as a part of popa3d,
 * a POP3 server:
 *
 *	http://www.openwall.com/popa3d/
 */
 
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <limits.h>
 
char *concat(const char *s1, ...)
{
	va_list args;
	const char *s;
	char *p, *result;
	unsigned long l, m, n;
 
	m = n = strlen(s1);
	va_start(args, s1);
	while ((s = va_arg(args, char *))) {
		l = strlen(s);
		if ((m += l) < l) break;
	}
	va_end(args);
	if (s || m >= INT_MAX) return NULL;
 
	result = (char *)malloc(m + 1);
	if (!result) return NULL;
 
	memcpy(p = result, s1, n);
	p += n;
	va_start(args, s1);
	while ((s = va_arg(args, char *))) {
		l = strlen(s);
		if ((n += l) < l || n > m) break;
		memcpy(p, s, l);
		p += l;
	}
	va_end(args);
	if (s || m != n || p != result + n) {
		free(result);
		return NULL;
	}
 
	*p = 0;
	return result;
}
 
#ifdef TEST
#include <stdio.h>
 
int main(int argc, char **argv)
{
	puts(concat(argv[0], argv[1], argv[2], argv[3], NULL));
	return 0;
}
#endif

Back to other source code snippets and frameworks placed in the public domain.

people/solar/software/public-domain-source-code/concat.txt · Last modified: 2011/02/04 14:07 by solar
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate to DokuWiki Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki Powered by OpenVZ Powered by Openwall GNU/*/Linux Bookmark and Share