Fix potential buffer overflow

* vsprintf() can overflow the output buffer; use vsnprintf() instead.
* unnecessary calls to strlen()
 - on every iteration just to see if the string end has been reached yet,
 - even though the upper bound can be derived from the return value of vsnprintf().

Unfortunately Microsoft's CRT returns a non-standard value, if vsnprintf() wants to write more than 'size' chars, so I handled that case differently in a wrapper around vsnprintf().