|
|
#define _XOPEN_SOURCE 600 |
|
|
#define _GNU_SOURCE |
|
|
#include <stdarg.h> |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <limits.h> |
|
|
|
|
|
#include "xmlrpc_config.h" |
|
|
#include "xmlrpc-c/string_int.h" |
|
|
#include "bool.h" |
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void |
|
|
newVsnprintf(char * const buffer, |
|
|
size_t const bufferSize, |
|
|
const char * const fmt, |
|
|
va_list varargs, |
|
|
size_t * const formattedSizeP) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bufferSize > INT_MAX/2) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = 0; |
|
|
} else { |
|
|
int rc; |
|
|
|
|
|
rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs); |
|
|
|
|
|
if (rc < 0) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = bufferSize * 2; |
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = rc; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static __inline__ int |
|
|
simpleVasprintf(char ** const resultP, |
|
|
const char * const fmt, |
|
|
va_list varargs) { |
|
|
|
|
|
|
|
|
|
|
|
int retval; |
|
|
char * buffer; |
|
|
size_t bufferSize; |
|
|
bool outOfMemory; |
|
|
|
|
|
for (buffer = NULL, bufferSize = 4096, outOfMemory = false; |
|
|
!buffer && !outOfMemory; |
|
|
) { |
|
|
|
|
|
buffer = malloc(bufferSize); |
|
|
if (!buffer) |
|
|
outOfMemory = true; |
|
|
else { |
|
|
size_t bytesNeeded; |
|
|
newVsnprintf(buffer, bufferSize, fmt, varargs, &bytesNeeded); |
|
|
if (bytesNeeded > bufferSize) { |
|
|
free(buffer); |
|
|
buffer = NULL; |
|
|
bufferSize = bytesNeeded; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (outOfMemory) |
|
|
retval = -1; |
|
|
else { |
|
|
retval = strlen(buffer); |
|
|
*resultP = buffer; |
|
|
} |
|
|
return retval; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char * const xmlrpc_strsol = |
|
|
"[insufficient memory to build string]"; |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
xmlrpc_strnomem(const char * const string) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return string == xmlrpc_strsol; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char * |
|
|
xmlrpc_strnomemval() { |
|
|
|
|
|
return xmlrpc_strsol; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
xmlrpc_vasprintf(const char ** const retvalP, |
|
|
const char * const fmt, |
|
|
va_list varargs) { |
|
|
|
|
|
char * string; |
|
|
int rc; |
|
|
|
|
|
#if HAVE_ASPRINTF |
|
|
rc = vasprintf(&string, fmt, varargs); |
|
|
#else |
|
|
rc = simpleVasprintf(&string, fmt, varargs); |
|
|
#endif |
|
|
|
|
|
if (rc < 0) |
|
|
*retvalP = xmlrpc_strsol; |
|
|
else |
|
|
*retvalP = string; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void XMLRPC_PRINTF_ATTR(2,3) |
|
|
xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) { |
|
|
|
|
|
va_list varargs; |
|
|
|
|
|
va_start(varargs, fmt); |
|
|
|
|
|
xmlrpc_vasprintf(retvalP, fmt, varargs); |
|
|
|
|
|
va_end(varargs); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char * |
|
|
xmlrpc_strdupsol(const char * const string) { |
|
|
|
|
|
const char * retvalOrNull; |
|
|
|
|
|
retvalOrNull = strdup(string); |
|
|
|
|
|
return retvalOrNull ? retvalOrNull : xmlrpc_strsol; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
xmlrpc_strfree(const char * const string) { |
|
|
|
|
|
if (string != xmlrpc_strsol) |
|
|
free((void *)string); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char * |
|
|
xmlrpc_strdupnull(const char * const string) { |
|
|
|
|
|
if (string) |
|
|
return strdup(string); |
|
|
else |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
xmlrpc_strfreenull(const char * const string) { |
|
|
|
|
|
if (string) |
|
|
xmlrpc_strfree(string); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|