From 571fdb2ad46675785de1c9274def586b22b6976b Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Mon, 22 Apr 2024 21:57:43 -0600 Subject: [PATCH 1/2] libgis: G_vasprintf bug fix --- lib/gis/asprintf.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/gis/asprintf.c b/lib/gis/asprintf.c index ea2e0c7f5d4..671e652d1ce 100644 --- a/lib/gis/asprintf.c +++ b/lib/gis/asprintf.c @@ -43,23 +43,21 @@ int G_vasprintf(char **out, const char *fmt, va_list ap) #ifdef HAVE_ASPRINTF return vasprintf(out, fmt, ap); #else + va_list aq; size_t size = strlen(fmt) + 50; char *buf = G_malloc(size); int count; - for (;;) { - /* BUG: according to man vsnprintf, - * va_start() should be called immediately before vsnprintf(), - * and va_end() immediately after vsnprintf() - * otherwise there will be memory corruption */ - count = vsnprintf(buf, size, fmt, ap); - if (count >= 0 && count < size) - break; - size *= 2; - buf = G_realloc(buf, size); + va_copy(aq, ap); + count = vsnprintf(buf, size, fmt, ap); + if (count++ >= size) { + buf = G_realloc(buf, count); + if (count - 1 == size) + buf[count] = '\0'; + else + vsnprintf(buf, count, fmt, aq); } - - buf = G_realloc(buf, count + 1); + va_end(aq); *out = buf; return count; From 2de3f429b92f3647bdd3da452dd6693742b3a1e6 Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Mon, 22 Apr 2024 23:50:14 -0600 Subject: [PATCH 2/2] Fix G_rasprintf as well --- lib/gis/asprintf.c | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/lib/gis/asprintf.c b/lib/gis/asprintf.c index 671e652d1ce..4256aa43ea1 100644 --- a/lib/gis/asprintf.c +++ b/lib/gis/asprintf.c @@ -44,19 +44,17 @@ int G_vasprintf(char **out, const char *fmt, va_list ap) return vasprintf(out, fmt, ap); #else va_list aq; - size_t size = strlen(fmt) + 50; - char *buf = G_malloc(size); + char *buf; + size_t size; int count; va_copy(aq, ap); - count = vsnprintf(buf, size, fmt, ap); - if (count++ >= size) { - buf = G_realloc(buf, count); - if (count - 1 == size) - buf[count] = '\0'; - else - vsnprintf(buf, count, fmt, aq); - } + /* determine a sufficient size */ + count = vsnprintf(NULL, 0, fmt, ap); + /* count holds the number of printable characters; size must be +1 for '\0' + */ + buf = G_malloc(size = ++count); + count = vsnprintf(buf, size, fmt, aq); va_end(aq); *out = buf; @@ -98,29 +96,22 @@ int G_asprintf(char **out, const char *fmt, ...) int G_rasprintf(char **out, size_t *size, const char *fmt, ...) { va_list ap; - int count; char *buf = *out; size_t osize = *size; + int count; - if (osize < strlen(fmt) + 50) { - osize = strlen(fmt) + 50; - buf = G_realloc(buf, osize); - } + va_start(ap, fmt); + count = vsnprintf(buf, osize, fmt, ap); + va_end(ap); - for (;;) { + if (count >= osize) { + /* count holds the number of printable characters; osize must be +1 for + * '\0' */ + buf = G_realloc(buf, osize = ++count); va_start(ap, fmt); count = vsnprintf(buf, osize, fmt, ap); va_end(ap); - if (count >= 0 && (size_t)count < osize) - break; - if (count > -1) - osize = count + 1; - else - osize *= 2; - - buf = G_realloc(buf, osize); } - *out = buf; *size = osize;