As for the related snprintf(), etc., well, at least destination is
NUL terminated, even if the truncation could cause data loss. They
too need looking at and replacing in time.
uvsnprintf() could be implemented in terms of asprintf(), strlen(),
strcpy(), and free().
Yes, I like asprintf(), but it's not POSIX. snprintf(NULL, 0, fmt, ...)
is POSIX and returns the strlen() of what would have been written,
allowing a second call to do the work, again, for real this time.
We could avoid the double effort on most occasions by tracking the size
of the existing allocation and only realloc() when it's not big enough.
vsnprintf(3) exists so our function can pass on the va_list to it.
On a related note, I've a header file that does the frequently seen
double-size-and-realloc test on appending to an array, not just char,
so that duplication can be whittled down.