W załączonych łatkach moim zdaniem są błędy off-by-one, podobnie zresztą jak jest w aktualnym kodzie libgadu. Przypadek res == size oznacza, że wszystkie znaki poza nullem zostały zapisane i implementacje niezgodne z C99, w szczególności MSVC, mogą takie coś zwrócić. Natomiast przypadek res == size - 1 oznacza, że wszystko idealnie się zmieściło. Ponadto w pętli dla nie-C99 brakowało dodatkowych va_copy(). Kolejny problem to brak implementacji va_copy() dla MSVC.
Załączam moją wersję łatki. Pozdrawiam, Bartosz
From ea2965b436c8f491587b8915d3b9da469ed90c26 Mon Sep 17 00:00:00 2001 From: Bartosz Brachaczek <b.brachac...@gmail.com> Date: Sat, 29 Oct 2011 01:40:33 +0200 Subject: [PATCH] Popraw gg_vsaprintf() dla nie-C99 --- src/common.c | 58 ++++++++++++++++++++++++++++------------------------------ 1 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/common.c b/src/common.c index 14eb5f3..afd9c7a 100644 --- a/src/common.c +++ b/src/common.c @@ -43,6 +43,14 @@ #include "libgadu.h" +#ifndef GG_CONFIG_HAVE_VA_COPY +# ifdef GG_CONFIG_HAVE___VA_COPY +# define va_copy(dest, src) __va_copy((dest), (src)) +# else +# define va_copy(dest, src) (dest) = (src) +# endif +#endif + /** * \internal Odpowiednik funkcji \c vsprintf alokujący miejsce na wynik. * @@ -58,59 +66,49 @@ */ char *gg_vsaprintf(const char *format, va_list ap) { - int size = 0; + int size; char *buf = NULL; - -#ifdef GG_CONFIG_HAVE_VA_COPY va_list aq; - va_copy(aq, ap); -#else -# ifdef GG_CONFIG_HAVE___VA_COPY - va_list aq; - - __va_copy(aq, ap); -# endif -#endif - #ifndef GG_CONFIG_HAVE_C99_VSNPRINTF { - int res; + int res = 0; char *tmp; size = 128; do { - size *= 2; + if (res > size) { + /* Jednak zachowanie zgodne z C99. */ + size = res + 1; + } else { + size *= 2; + } + if (!(tmp = realloc(buf, size))) { free(buf); return NULL; } + buf = tmp; - res = vsnprintf(buf, size, format, ap); - } while (res == size - 1 || res == -1); + va_copy(aq, ap); + res = vsnprintf(buf, size, format, aq); + va_end(aq); + } while (res >= size || res < 0); } #else { char tmp[2]; + va_copy(aq, ap); /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc * musimy podać coś istniejącego jako cel printf()owania. */ - size = vsnprintf(tmp, sizeof(tmp), format, ap); - if (!(buf = malloc(size + 1))) + size = vsnprintf(tmp, sizeof(tmp), format, aq) + 1; + va_end(aq); + if (!(buf = malloc(size))) return NULL; - } -#endif -#ifdef GG_CONFIG_HAVE_VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -#else -# ifdef GG_CONFIG_HAVE___VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -# else - vsnprintf(buf, size + 1, format, ap); -# endif + vsnprintf(buf, size, format, ap); + } #endif return buf; -- 1.7.7
_______________________________________________ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel