1 #include "stdio_impl.h"
2 #include <errno.h>
3 #include <limits.h>
4 #include <stdint.h>
5 #include <string.h>
6 
sn_write(FILE * f,const unsigned char * s,size_t l)7 static size_t sn_write(FILE* f, const unsigned char* s, size_t l) {
8     size_t k = f->wend - f->wpos;
9     if (k > l)
10         k = l;
11     memcpy(f->wpos, s, k);
12     f->wpos += k;
13     /* pretend to succeed, but discard extra data */
14     return l;
15 }
16 
vsnprintf(char * restrict s,size_t n,const char * restrict fmt,va_list ap)17 int vsnprintf(char* restrict s, size_t n, const char* restrict fmt, va_list ap) {
18     int r;
19     char b;
20     FILE f = {.lbf = EOF, .write = sn_write, .lock = -1};
21 
22     if (n - 1 > INT_MAX - 1) {
23         if (n) {
24             errno = EOVERFLOW;
25             return -1;
26         }
27         s = &b;
28         n = 1;
29     }
30 
31     /* Ensure pointers don't wrap if "infinite" n is passed in */
32     if (n > SIZE_MAX - (uintptr_t)s - 1)
33         n = SIZE_MAX - (uintptr_t)s - 1;
34     f.buf_size = n;
35     f.buf = f.wpos = (void*)s;
36     f.wbase = f.wend = (void*)(s + n);
37     r = vfprintf(&f, fmt, ap);
38 
39     /* Null-terminate, overwriting last char if dest buffer is full */
40     if (n)
41         f.wpos[-(f.wpos == f.wend)] = 0;
42     return r;
43 }
44