lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 30 Nov 2006 04:41:35 +0300
From: Solar Designer <solar@...nwall.com>
To: bugtraq@...urityfocus.com, gnupg-devel@...pg.org
Subject: safely concatenating strings in portable C (Re: GnuPG 1.4 and 2.0 buffer overflow)

On Mon, Nov 27, 2006 at 06:13:02PM +0100, Werner Koch wrote:
> +    n = strlen(s) + (defname?strlen (defname):0) + 10;
>      prompt = xmalloc(n);
>      if( defname )
>         sprintf(prompt, "%s [%s]: ", s, defname );
...
> Note, that using snprintf would not have helped in
> this case.  How I wish C-90 had introduced asprintf or at least it
> would be available on more platforms.

Actually, if you dare to use snprintf() (either because you don't need
your code to be portable to platforms that lack snprintf() or because
you provide an implementation along with your application), then
implementing asprintf() on top of snprintf() is fairly easy (although
you do need to consider both snprintf() return value conventions).

However, in those (most common) cases when all you need is to concatenate
strings, relying on or providing an snprintf() implementation might be
an overkill.  For that reason, I wrote a trivial concat() function (for
popa3d) that should be much easier to audit than a full-blown *printf().
Please feel free to reuse it in any applications with no need to even
credit me (consider it hereby placed in the public domain, or you may
use it under the terms of the popa3d LICENSE).

The usage of concat() is as follows:

	prompt = concat(s, " [", defname, "]: ", NULL);

You may also define an xconcat() (that would exit the program if the
allocation fails).

The code may be found here:

	http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/popa3d/popa3d/misc.c?rev=HEAD

(it's the last function currently defined in that source file), or here
is the current revision:

#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <limits.h>

char *concat(char *s1, ...)
{
	va_list args;
	char *s, *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 = 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;
}

-- 
Alexander Peslyak <solar at openwall.com>
GPG key ID: 5B341F15  fp: B3FB 63F4 D7A3 BCCC 6F6E  FC55 A2FC 027C 5B34 1F15
http://www.openwall.com - bringing security into open computing environments

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ