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