Home page logo
/

bugtraq logo Bugtraq mailing list archives

Re: safely concatenating strings in portable C (Re: GnuPG 1.4 and 2.0 buffer overflow)
From: Simon Josefsson <simon () josefsson org>
Date: Fri, 01 Dec 2006 10:45:06 +0100

Solar Designer <solar () openwall com> writes:

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.

Gnulib's xvasprintf detects %s...%s format strings, which makes the
code easy to analyse for that case.  (Note that the x* memory
allocation functions never returns NULL, it exits the program
instead.)  Unfortunately, it doesn't seem like this optimization has
been ported to gnulib's non-x* printf replacement functions (snprintf,
asprintf etc) yet.

/Simon

static inline char *
xstrcat (size_t argcount, va_list args)
{
  char *result;
  va_list ap;
  size_t totalsize;
  size_t i;
  char *p;

  /* Determine the total size.  */
  totalsize = 0;
  va_copy (ap, args);
  for (i = argcount; i > 0; i--)
    {
      const char *next = va_arg (ap, const char *);
      totalsize = xsum (totalsize, strlen (next));
    }
  va_end (ap);

  /* Test for overflow in the summing pass above or in (totalsize + 1) below.
     Also, don't return a string longer than INT_MAX, for consistency with
     vasprintf().  */
  if (totalsize == SIZE_MAX || totalsize > INT_MAX)
    {
      errno = EOVERFLOW;
      return NULL;
    }

  /* Allocate and fill the result string.  */
  result = XNMALLOC (totalsize + 1, char);
  p = result;
  for (i = argcount; i > 0; i--)
    {
      const char *next = va_arg (args, const char *);
      size_t len = strlen (next);
      memcpy (p, next, len);
      p += len;
    }
  *p = '\0';

  return result;
}

char *
xvasprintf (const char *format, va_list args)
{
  char *result;

  /* Recognize the special case format = "%s...%s".  It is a frequently used
     idiom for string concatenation and needs to be fast.  We don't want to
     have a separate function xstrcat() for this purpose.  */
  {
    size_t argcount = 0;
    const char *f;

    for (f = format;;)
      {
        if (*f == '\0')
          /* Recognized the special case of string concatenation.  */
          return xstrcat (argcount, args);
        if (*f != '%')
          break;
        f++;
        if (*f != 's')
          break;
        f++;
        argcount++;
      }
  }

  if (vasprintf (&result, format, args) < 0)
    {
      if (errno == ENOMEM)
        xalloc_die ();
      return NULL;
    }

  return result;
}


  By Date           By Thread  

Current thread:
  • Re: safely concatenating strings in portable C (Re: GnuPG 1.4 and 2.0 buffer overflow) Simon Josefsson (Dec 02)
[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]
AlienVault