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

Reply via email to