mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-24 11:54:49 +00:00
Added workaround for non-compliant runtimes in alloc_vprintf()
This commit is contained in:
1 parent
60858d7fe5
commit
c9036f3ac0
2 files changed
+49
-13
No files matched your search
+24
-13
@@ -731,21 +731,32 @@ static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
va_list ap_copy;
|
||||
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);
|
||||
len = vsnprintf(NULL, 0, fmt, ap_copy);
|
||||
len = vsnprintf(*buf, size, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
|
||||
if (len > (int) size &&
|
||||
(size = len + 1) > 0 &&
|
||||
(*buf = (char *) malloc(size)) == NULL) {
|
||||
len = -1; // Allocation failed, mark failure
|
||||
} else {
|
||||
va_copy(ap_copy, ap);
|
||||
vsnprintf(*buf, size, fmt, ap_copy);
|
||||
if (len < 0) {
|
||||
// eCos and Windows are not standard-compliant and return -1 when
|
||||
// the buffer is too small. Keep allocating larger buffers until we
|
||||
// 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 {
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, len + 1, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
+25
@@ -613,6 +613,30 @@ static const char *test_rewrites(void) {
|
||||
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) {
|
||||
RUN_TEST(test_should_keep_alive);
|
||||
RUN_TEST(test_match_prefix);
|
||||
@@ -630,6 +654,7 @@ static const char *run_all_tests(void) {
|
||||
RUN_TEST(test_mg_connect);
|
||||
RUN_TEST(test_mg_set_option);
|
||||
RUN_TEST(test_rewrites);
|
||||
RUN_TEST(test_alloc_vprintf);
|
||||
#ifdef MONGOOSE_USE_SSL
|
||||
RUN_TEST(test_ssl);
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user