static __inline__ void simpleVasprintf(char ** const retvalP, const char * const fmt, va_list varargs) { /*---------------------------------------------------------------------------- This is a poor man's implementation of vasprintf(), of GNU fame. -----------------------------------------------------------------------------*/ size_t const initialSize = 4096; char * result; result = malloc(initialSize); if (result != NULL) { size_t bytesNeeded; bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs); if (bytesNeeded > initialSize) { free(result); result = malloc(bytesNeeded); if (result != NULL) XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs); } else if (bytesNeeded == initialSize) { if (result[initialSize-1] != '\0') { /* This is one of those old systems where vsnprintf() returns the number of bytes it used, instead of the number that it needed, and it in fact needed more than we gave it. Rather than mess with this highly unlikely case (old system and string > 4095 characters), we just treat this like an out of memory failure. */ free(result); result = NULL; } } } *retvalP = result; }
static void formatOut(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, const char * const formatString, ...) { /*---------------------------------------------------------------------------- A lightweight print routine for use with various serialization functions. Use this routine only for printing small objects -- it uses a fixed-size internal buffer and returns an error on overflow. In particular, do NOT use this routine to print XML-RPC string values! -----------------------------------------------------------------------------*/ va_list args; char buffer[128]; int rc; XMLRPC_ASSERT_ENV_OK(envP); va_start(args, formatString); rc = XMLRPC_VSNPRINTF(buffer, sizeof(buffer), formatString, args); /* Old vsnprintf() (and Windows) fails with return value -1 if the full string doesn't fit in the buffer. New vsnprintf() puts whatever will fit in the buffer, and returns the length of the full string regardless. For us, this truncation is a failure. */ if (rc < 0) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); else { unsigned int const formattedLen = rc; if (formattedLen + 1 >= (sizeof(buffer))) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); else XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, formattedLen); } va_end(args); }
static __inline__ void newVsnprintf(char * const buffer, size_t const bufferSize, const char * const fmt, va_list varargs, size_t * const formattedSizeP) { /*---------------------------------------------------------------------------- This is vsnprintf() with the new behavior, where not fitting in the buffer is not a failure. Unfortunately, we can't practically return the size of the formatted string if the C library has old vsnprintf() and the formatted string doesn't fit in the buffer, so in that case we just return something larger than the buffer. -----------------------------------------------------------------------------*/ if (bufferSize > INT_MAX/2) { /* There's a danger we won't be able to coerce the return value of XMLRPC_VSNPRINTF to an integer (which we have to do because, while for POSIX its return value is ssize_t, on Windows it is int), or return double the buffer size. */ *formattedSizeP = 0; } else { int rc; rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs); if (rc < 0) { /* We have old vsnprintf() (or Windows) and the formatted value doesn't fit in the buffer, but we don't know how big a buffer it needs. */ *formattedSizeP = bufferSize * 2; } else { /* Either the string fits in the buffer or we have new vsnprintf() which tells us how big the string is regardless. */ *formattedSizeP = rc; } } }
static void formatOut(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, const char * const formatString, ...) { /*---------------------------------------------------------------------------- A lightweight print routine for use with various serialization functions. Use this routine only for printing small objects -- it uses a fixed-size internal buffer and returns an error on overflow. In particular, do NOT use this routine to print XML-RPC string values! -----------------------------------------------------------------------------*/ va_list args; char buffer[SMALL_BUFFER_SZ]; int count; XMLRPC_ASSERT_ENV_OK(envP); va_start(args, formatString); count = XMLRPC_VSNPRINTF(buffer, SMALL_BUFFER_SZ, formatString, args); /* Old C libraries return -1 if vsnprintf overflows its buffer. ** New C libraries return the number of characters which *would* have ** been printed if the error did not occur. This is impressively vile. ** Thank the C99 committee for this bright idea. But wait! We also ** need to keep track of the trailing NUL. */ if (count < 0 || count >= (SMALL_BUFFER_SZ - 1)) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); else XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, count); va_end(args); }