Re: better snprintf replacement, anyone?

Theo de Raadt (deraadt@CVS.OPENBSD.ORG)
Tue, 22 Jul 1997 16:45:12 -0600

> >Let me give you an example of what you suggest:
> >
> > if (strlen(a) + 1 + 10 + 3 + 1 + 10 + 4*sizeof(long) + 1 + strlen(b) +
> > 1 + strlen(c) + 2 >= sizeof buf);
> > sprintf(buf, "%s %d see %d %lx %s %s\n", a, i, j, p,
> > b, c);
> > else
> > goto bail; /* I really just wanted to truncate the string... */
>
> As a comment to support Theo's point of view, it's worth noting that
> the above example includes about 6 errors. I realize Theo probably
> whipped it up off the top of his head, but it does demonstrate the
> difficulty of this approach. It should be something like:
>
> #define N_DEC_DIGIT(type) ((((sizeof(type) * 8 - 1) * 30103 + 99999) \
> / 100000) + 1)
>
> if (strlen(a) + 1 + N_DEC_DIGIT(int) + 5 + N_DEC_DIGIT(int) + 1 +
> 2*sizeof(long) + 1 + strlen(b) + 1 + strlen(c) + 2 <= sizeof buf)
> {
> sprintf(buf, "%s %d see %d %lx %s %s\n", a, i, j, p, b, c);
> } else {
> goto bail; /* I really just wanted to truncate the string... */
> }
>
> (For those puzzled about N_DEC_DIGIT: log10(2) ~= .30103 and the sign bit
> doesn't count).

Incredible Peter -- you've proved the point far better than I could
have. (What a disgusting, complicated, overworked, and error-prone
mess).

I would prefer to just analyze what happens when a truncation occurs,
and decide how to deal with that:

if (snprintf(buf, sizeof buf, %s %d see %d %lx %s %s\n",
a, i, j, p, b, c) >= sizeof buf)
/* deal with the buffer truncation */

However, in most cases truncation is OK.