From 6f6e12a94487f7bdf9efe2d5f1733684df6d75a6 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 19 Mar 2013 23:30:43 -0700 Subject: [PATCH] utils strbuf: Copy va_lists rather than using them twice. After a va_list has been passed to a function that uses va_arg(), the value of the va_list is undefined. Thus, rather copy the list before using it for the first time to make sure we've got a valid va_list object on the second usage. --- src/utils/strbuf.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/utils/strbuf.c b/src/utils/strbuf.c index df3ee4b..a48f7bc 100644 --- a/src/utils/strbuf.c +++ b/src/utils/strbuf.c @@ -105,6 +105,7 @@ sdb_strbuf_destroy(sdb_strbuf_t *strbuf) ssize_t sdb_strbuf_vappend(sdb_strbuf_t *strbuf, const char *fmt, va_list ap) { + va_list aq; int status; if ((! strbuf) || (! fmt)) @@ -116,21 +117,27 @@ sdb_strbuf_vappend(sdb_strbuf_t *strbuf, const char *fmt, va_list ap) if (strbuf_resize(strbuf)) return -1; + /* 'ap' is invalid after calling vsnprintf; thus copy before using it */ + va_copy(aq, ap); status = vsnprintf(strbuf->string + strbuf->pos, strbuf->size - strbuf->pos, fmt, ap); - if (status < 0) + if (status < 0) { + va_end(aq); return status; + } if ((size_t)status >= strbuf->size - strbuf->pos) { strbuf_resize(strbuf); /* reset string and try again */ strbuf->string[strbuf->pos] = '\0'; - return sdb_strbuf_vappend(strbuf, fmt, ap); + status = (int)sdb_strbuf_vappend(strbuf, fmt, aq); } + else + strbuf->pos += (size_t)status; - strbuf->pos += (size_t)status; + va_end(aq); return (ssize_t)status; } /* sdb_strbuf_vappend */ -- 2.30.2