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