snprintf() return value changes
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 17 Sep 2014 07:28:32 +0000 (00:28 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 17 Sep 2014 18:42:25 +0000 (11:42 -0700)
It's helpful for snprintf() to return 0, instead of an error code, when
it does no work.  A common pattern is something like:

len = 0;
len += snprintf(buf + len, bufsz - len, "whatever");
len += snprintf(buf + len, bufsz - len, "overflowed buf");
len += snprintf(buf + len, bufsz - len, "used to error");
len += snprintf(buf + len, bufsz - len, "and more text");

Once bufsz - len == 0, such as after the "overflow" print, future
snprintfs now return 0, and are basically nops.  Previously, the
snprintfs that error out would return a negative value, actually setting
length back slightly, allowing "and more text" to clobber a bit.

Additionally, the usual snprintf returns how many characters we
processed, regardless of whether or not we wrote them.  This is
unsuitable for marking progress through a buffer.  Now, we return how
many characters we wrote.

The current semantics: snprintf forces a null termination of the string,
but does not count that in the return value (similar to strlen()).  The
return value is the number of characters written.  If a buf has n bytes,
n-1 is the max return value, with the nth byte being set to 0.

This is a little different than normal snprintf, but is more useful for
our series-of-snprintfs pattern.  If we change it back, we'll need to be
careful of the signs of bufsz and len to make sure we don't pass in
large unsigned values and accidentally trigger a huge printf.

kern/src/printfmt.c

index d999339..8018966 100644 (file)
@@ -297,9 +297,10 @@ typedef struct sprintbuf {
 
 static void sprintputch(int ch, sprintbuf_t *NONNULL *NONNULL b)
 {
-       (*b)->cnt++;
-       if ((*b)->buf < (*b)->ebuf)
+       if ((*b)->buf < (*b)->ebuf) {
                *((*b)->buf++) = ch;
+               (*b)->cnt++;
+       }
 }
 
 int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
@@ -307,8 +308,9 @@ int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
        sprintbuf_t b;// = {buf, buf+n-1, 0};
        sprintbuf_t *COUNT(1) NONNULL bp = &b;
 
+       /* this isn't quite the snprintf 'spec', but errors aren't helpful */
        if (buf == NULL || n < 1)
-               return -EINVAL;
+               return 0;
 
        b.buf = NULL; // zra : help out the Deputy optimizer a bit
        b.ebuf = buf+n-1;