1#include "stdio_impl.h"
2#include <errno.h>
3#include <limits.h>
4#include <stdint.h>
5#include <string.h>
6
7static 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
17int 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