[2206] in bugtraq

home help back first fref pref prev next nref lref last post

Re: syslog()/snprintf(): beware of functions with fuzzy specs

daemon@ATHENA.MIT.EDU (Casper Dik)
Wed Sep 6 22:44:08 1995

Date:         Wed, 6 Sep 1995 16:39:10 +0200
Reply-To: Bugtraq List <BUGTRAQ@CRIMELAB.COM>
From: Casper Dik <casper@Holland.Sun.COM>
X-To:         Bugtraq List <BUGTRAQ@CRIMELAB.COM>
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@CRIMELAB.COM>
In-Reply-To:  Your message of "Fri, 01 Sep 1995 17:23:53 PDT."
              <199509020023.RAA29501@teal.us.oracle.com>

>BSD4.4 snprintf()s return the number of characters they would have
>written had the buffer been infinite.  This is despite the manual page
>saying they return the number of characters actually written.

This should be fixed.  It requires the *snprintf() code to parse
and examine all arguments: that isn't necessary.

And p += snprintf(p, &buf[sizeof(buf)] -p, ...)
won't work as expected.

>Number of characters written does not include the NULL.

(Aside: I prefer NUL to refer to '\0' and NULL to refer to the null pointer)

>GNU snprintf()s return the number of characters actually written (minus
>the NULL).  On a overflowed buffer, the GNU documentation conflicts with
>itself.  At one point it says, (bufsiz - 1) is returned, and in another
>example it says (bufsiz) is returned (but (bufsiz - 1) plus a NULL
>character are written).  I'm not sure what it does for real.

I'm pretty sure we want a terminated string.  I.e., return "bufsiz - 1".

>I've seen a few other cobbled version of *nprintf.  I'm best off with a
>dart board if I needed to apriori determine what they do on the boundary
>cases.
>
>Some important boundary cases:
>
>vsnprintf (buf, bufsiz, fmt, ap)
>
>  bufsiz = 0
>  bufsiz = 1
>  bufsiz = amount of chars sprint will use, less one for the null
>  bufsiz = amount of chars sprint will use, no room for null
>  bufsiz = less than amount of chars sprint will use
>
>Which return values of -1, 0, bufsiz - 1, bufsiz, or >bufsiz (heaven
>forbid a core dump)?  Do they write on buf[bufsiz]?  What do they write
>to buf?  What is the state of NULL terminatation on each of the
>sitations above?  Many different answers have I seen.

snsprintf should never write buf[bufsize], it can write buf[bufsize-1].

I prefer the following:

        bufsiz          strsize                 return value
         0               N/A                     0  (can argue in favour of -1)
         1               N/A                     0
         >1              <bufsiz                 strsize
         >1              >=bufsiz                bufsiz-1

It can be argued that snprintf(buf, 0, ...) should return -1: there's
no room for the '\0'.

But you also want p += snprintf(....) to continue to work.

(But note that if you do that properly, the remaining number of bytes
will never drop below 1)

>For those of you working on syslog patches using *nprintf, you will do
>the world a favor if you make it explicitly clear the semantics you
>expect.

Or ignore the return value and use strlen().  (In which case you
depend on snprintf to return '\0' terminated strings.)

Casper

home help back first fref pref prev next nref lref last post