X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fstdio%2Fvsnprintf.c;h=6f19b0287234bd6f9ff414f5dfd490a563a77bd3;hp=1f316ca48207f986a6dd0617269e85f3e977fc06;hb=f1b23d41cff432a8d0939af427fa005b4a4f95d7;hpb=9ae8d5fc71a4b61ec826d58f03f7b543755fb1d4 diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c index 1f316ca4..6f19b028 100644 --- a/src/stdio/vsnprintf.c +++ b/src/stdio/vsnprintf.c @@ -2,33 +2,37 @@ static size_t sn_write(FILE *f, const unsigned char *s, size_t l) { - /* pretend to succeed, but discard data */ + size_t k = f->wend - f->wpos; + if (k > l) k = l; + memcpy(f->wpos, s, k); + f->wpos += k; + /* pretend to succeed, but discard extra data */ return l; } -int vsnprintf(char *s, size_t n, const char *fmt, va_list ap) +int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) { int r; - FILE f; - unsigned char buf[1]; + char b; + FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 }; - memset(&f, 0, sizeof(FILE)); - f.lbf = EOF; - f.write = sn_write; - f.buf_size = 1; - f.buf = buf; - f.lock = -1; - if (n > INT_MAX) { - errno = EOVERFLOW; - return -1; - } else if (n > 0) { - if (n > (char *)0+SIZE_MAX-s) n = (char *)0+SIZE_MAX-s; - f.wpos = (void *)s; - f.wbase = f.wend = (void *)(s+n-1); - f.wstop = f.wend - 1; + if (n-1 > INT_MAX-1) { + if (n) { + errno = EOVERFLOW; + return -1; + } + s = &b; + n = 1; } + + /* Ensure pointers don't wrap if "infinite" n is passed in */ + if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1; + f.buf_size = n; + f.buf = f.wpos = (void *)s; + f.wbase = f.wend = (void *)(s+n); r = vfprintf(&f, fmt, ap); - /* wpos points just after last byte written, or to s+n-1 (wbase) */ - *f.wpos = 0; + + /* Null-terminate, overwriting last char if dest buffer is full */ + if (n) f.wpos[-(f.wpos == f.wend)] = 0; return r; }