Commit c9036f3a authored by Sergey Lyubka's avatar Sergey Lyubka

Added workaround for non-compliant runtimes in alloc_vprintf()

parent 60858d7f
...@@ -731,21 +731,32 @@ static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) { ...@@ -731,21 +731,32 @@ static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) {
va_list ap_copy; va_list ap_copy;
int len; int len;
// Windows is not standard-compliant, and vsnprintf() returns -1 if
// buffer is too small. Also, older versions of msvcrt.dll do not have
// _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
// Therefore, we make two passes: on first pass, get required message length.
// On second pass, actually print the message.
va_copy(ap_copy, ap); va_copy(ap_copy, ap);
len = vsnprintf(NULL, 0, fmt, ap_copy); len = vsnprintf(*buf, size, fmt, ap_copy);
va_end(ap_copy);
if (len > (int) size && if (len < 0) {
(size = len + 1) > 0 && // eCos and Windows are not standard-compliant and return -1 when
(*buf = (char *) malloc(size)) == NULL) { // the buffer is too small. Keep allocating larger buffers until we
len = -1; // Allocation failed, mark failure // succeed or out of memory.
*buf = NULL;
while (len < 0) {
if (*buf) free(*buf);
size *= 2;
if ((*buf = (char *) malloc(size)) == NULL) break;
va_copy(ap_copy, ap);
len = vsnprintf(*buf, size, fmt, ap_copy);
va_end(ap_copy);
}
} else if (len > (int) size) {
// Standard-compliant code path. Allocate a buffer that is large enough.
if ((*buf = (char *) malloc(len + 1)) == NULL) {
len = -1;
} else { } else {
va_copy(ap_copy, ap); va_copy(ap_copy, ap);
vsnprintf(*buf, size, fmt, ap_copy); len = vsnprintf(*buf, len + 1, fmt, ap_copy);
va_end(ap_copy);
}
} }
return len; return len;
......
...@@ -613,6 +613,30 @@ static const char *test_rewrites(void) { ...@@ -613,6 +613,30 @@ static const char *test_rewrites(void) {
return NULL; return NULL;
} }
static int avt(char **buf, size_t buf_size, const char *fmt, ...) {
int result;
va_list ap;
va_start(ap, fmt);
result = alloc_vprintf(buf, buf_size, fmt, ap);
va_end(ap);
return result;
}
static const char *test_alloc_vprintf(void) {
char buf[5], *p = buf;
ASSERT(avt(&p, sizeof(buf), "%d", 123) == 3);
ASSERT(p == buf);
ASSERT(strcmp(p, "123") == 0);
ASSERT(avt(&p, sizeof(buf), "%d", 123456789) == 9);
ASSERT(p != buf);
ASSERT(strcmp(p, "123456789") == 0);
free(p);
return NULL;
}
static const char *run_all_tests(void) { static const char *run_all_tests(void) {
RUN_TEST(test_should_keep_alive); RUN_TEST(test_should_keep_alive);
RUN_TEST(test_match_prefix); RUN_TEST(test_match_prefix);
...@@ -630,6 +654,7 @@ static const char *run_all_tests(void) { ...@@ -630,6 +654,7 @@ static const char *run_all_tests(void) {
RUN_TEST(test_mg_connect); RUN_TEST(test_mg_connect);
RUN_TEST(test_mg_set_option); RUN_TEST(test_mg_set_option);
RUN_TEST(test_rewrites); RUN_TEST(test_rewrites);
RUN_TEST(test_alloc_vprintf);
#ifdef MONGOOSE_USE_SSL #ifdef MONGOOSE_USE_SSL
RUN_TEST(test_ssl); RUN_TEST(test_ssl);
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment