Index: src/of_asprintf.m ================================================================== --- src/of_asprintf.m +++ src/of_asprintf.m @@ -97,43 +97,39 @@ #ifndef HAVE_ASPRINTF static int vasprintf(char **string, const char *format, va_list arguments) { - int expectedLength, length; - va_list argumentsCopy; - - va_copy(argumentsCopy, arguments); - - expectedLength = vsnprintf(NULL, 0, format, argumentsCopy); - if (expectedLength == -1) - /* - * We have no way to know how large it is. Let's try 64 KB and - * hope. - */ - expectedLength = 65535; - - if ((*string = malloc((size_t)expectedLength + 1)) == NULL) - return -1; - - length = vsnprintf(*string, (size_t)expectedLength + 1, - format, arguments); - - if (length == -1 || length > expectedLength) { + size_t length, bufferLength = 128; + + *string = NULL; + + for (;;) { free(*string); - *string = NULL; - return -1; + + if ((*string = malloc(bufferLength)) == NULL) + return -1; + + length = vsnprintf(*string, bufferLength - 1, format, + arguments); + + if (length > 0 && (size_t)length < bufferLength - 1) + break; + + if (bufferLength > INT_MAX / 2) { + free(*string); + return -1; + } + + bufferLength <<= 1; } - /* - * In case we could not determine the size, resize to the actual size - * needed, but ignore any failure to do so. - */ - if (length < expectedLength) { - char *resized; - - if ((resized = realloc(*string, length + 1)) != NULL) + if (length != bufferLength - 1) { + char *resized = realloc(*string, length + 1); + + /* Ignore if making it smaller failed. */ + if (resized != NULL) *string = resized; } return length; }