<URL: http://bugs.freeciv.org/Ticket/Display.html?id=36496 >

Besides potential crashes like the one reported in PR#36441 there's the
problem that libutf8's vsnprintf() function doesn't work on Windows
Vista, as was reported on the forums a while ago:
http://forum.freeciv.org/viewtopic.php?t=2642

While searching for the cause of the crash of PR#36441 I noticed the
vsnprintf() replacement code in support.c for platforms where a native
vsnprintf() does not exist or is broken. I tried to activate it by
undefining HAVE_VSNPRINTF and HAVE_WORKING_VSNPRINTF in config.h and
compiled without using libutf8 and it seems to work fine even with
reordered arguments (PR#12932). Then I wrote a little test:

char buf1[100], buf2[100], buf3[100];
printf("printf: %2$s %1$s\n", "arg1", "arg2");
sprintf(buf1, "sprintf: %2$s %1$s\n", "arg1", "arg2");
snprintf(buf2, 100, "snprintf: %2$s %1$s\n", "arg1", "arg2");
my_snprintf(buf3, 100, "my_snprintf: %2$s %1$s\n", "arg1", "arg2");
printf("%s%s%s", buf1, buf2, buf3);

which resulted in:

printf: arg2 arg1
sprintf: arg2 arg1
snprintf: $s $s
my_snprintf: arg2 arg1

So it turns out that only the native snprintf() and vsnprintf()
functions are broken on Windows. My suggestion is now to replace any
remaining calls to snprintf() in S2_0 and S2_1 by calls to my_snprintf()
or cat_snprintf() and to skip the vsnprintf() tests in the configure
script on Windows, so the replacement code is being used. Then we
wouldn't need to use libutf8 anymore. Patches are attached. 

Index: configure.ac
===================================================================
--- configure.ac	(revision 12680)
+++ configure.ac	(working copy)
@@ -356,18 +356,6 @@
   AC_DEFINE_UNQUOTED(LOCALEDIR, "./share/locale", [Locale directory (windows)])
 fi  
 
-dnl Check libUTF8
-AC_ARG_WITH(libutf8,
-            AC_HELP_STRING([--with-libutf8],
-               [Use the libutf8 library (needed for some systems)]),
-            [with_libutf8=$withval], [with_libutf8=no])
-if test "$MINGW32" = yes || test "$with_libutf8" = yes; then
-  AC_CHECK_HEADER(libutf8.h, [],
-                  AC_MSG_ERROR([Could not find libutf8 library (libutf8.h)]))
-  AC_DEFINE(HAVE_LIBUTF8_H, 1, [Use libutf8's stdio functions])
-  LIBS="$LIBS -lutf8"
-fi
-
 dnl Check for zlib (needed for libpng)
 AC_CHECK_LIB(z, gzgets, , 
   AC_MSG_ERROR([Could not find zlib library.]), )
@@ -553,11 +541,16 @@
 AC_FUNC_FORK
 AC_FUNC_STRCOLL
 AC_FUNC_VPRINTF
+
+dnl Windows vsnprintf doesn't support argument reordering (see PR#12932)
+if test "x$MINGW32" != "xyes"; then
 AC_FUNC_VSNPRINTF
+AC_CHECK_FUNCS([vsnprintf])
+fi
 
 AC_CHECK_FUNCS([fileno ftime gethostname getpwuid inet_aton \
 		select snooze strerror strcasecmp strncasecmp \
-		strlcat strlcpy strstr usleep vsnprintf uname flock \
+		strlcat strlcpy strstr usleep uname flock \
 		gethostbyname connect bind])
 
 AC_MSG_CHECKING(for working gettimeofday)
Index: utility/support.h
===================================================================
--- utility/support.h	(revision 12680)
+++ utility/support.h	(working copy)
@@ -26,9 +26,6 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
-#ifdef HAVE_LIBUTF8_H
-#include <libutf8.h>
-#endif
 
 #ifdef TRUE
 #undef TRUE
Index: server/savegame.c
===================================================================
--- server/savegame.c	(revision 12680)
+++ server/savegame.c	(working copy)
@@ -1055,7 +1055,7 @@
         if (ptile->owner == NULL) {
           strcpy(token, "-");
         } else {
-          snprintf(token, sizeof(token), "%d", ptile->owner->player_no);
+          my_snprintf(token, sizeof(token), "%d", ptile->owner->player_no);
         }
         strcat(line, token);
         if (x + 1 < map.xsize) {
@@ -1075,7 +1075,7 @@
         if (ptile->owner_source == NULL) {
           strcpy(token, "-");
         } else {
-          snprintf(token, sizeof(token), "%d", ptile->owner_source->index);
+          my_snprintf(token, sizeof(token), "%d", ptile->owner_source->index);
         }
         strcat(line, token);
         if (x + 1 < map.xsize) {
Index: utility/support.h
===================================================================
--- utility/support.h	(revision 12680)
+++ utility/support.h	(working copy)
@@ -26,9 +26,6 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
-#ifdef HAVE_LIBUTF8_H
-#include <libutf8.h>
-#endif
 
 #ifdef TRUE
 #undef TRUE
Index: configure.ac
===================================================================
--- configure.ac	(revision 12680)
+++ configure.ac	(working copy)
@@ -355,18 +356,6 @@
   AC_DEFINE_UNQUOTED(LOCALEDIR, "./share/locale", [Locale directory (windows)])
 fi  
 
-dnl Check libUTF8
-AC_ARG_WITH(libutf8,
-            AC_HELP_STRING([--with-libutf8],
-               [Use the libutf8 library (needed for some systems)]),
-            [with_libutf8=$withval], [with_libutf8=no])
-if test "$MINGW32" = yes || test "$with_libutf8" = yes; then
-  AC_CHECK_HEADER(libutf8.h, [],
-                  AC_MSG_ERROR([Could not find libutf8 library (libutf8.h)]))
-  AC_DEFINE(HAVE_LIBUTF8_H, 1, [Use libutf8's stdio functions])
-  LIBS="$LIBS -lutf8"
-fi
-
 dnl Check for zlib (needed for libpng)
 AC_CHECK_LIB(z, gzgets, , 
   AC_MSG_ERROR([Could not find zlib library.]), )
@@ -547,11 +536,16 @@
 AC_FUNC_FORK
 AC_FUNC_STRCOLL
 AC_FUNC_VPRINTF
+
+dnl Windows vsnprintf doesn't support argument reordering (see PR#12932)
+if test "x$MINGW32" != "xyes"; then
 AC_FUNC_VSNPRINTF
+AC_CHECK_FUNCS([vsnprintf])
+fi
 
 AC_CHECK_FUNCS([fileno ftime gethostname getpwuid inet_aton \
 		select snooze strerror strcasecmp strncasecmp \
-		strlcat strlcpy strstr usleep vsnprintf uname flock \
+		strlcat strlcpy strstr usleep uname flock \
 		gethostbyname connect bind])
 
 AC_MSG_CHECKING(for working gettimeofday)
Index: client/tilespec.c
===================================================================
--- client/tilespec.c	(revision 12680)
+++ client/tilespec.c	(working copy)
@@ -1109,8 +1109,8 @@
   for (i = 0; i < num_cardinal_tileset_dirs; i++) {
     int value = (idx >> i) & 1;
 
-    snprintf(c + strlen(c), sizeof(c) - strlen(c), "%s%d",
-	     dir_get_tileset_name(cardinal_tileset_dirs[i]), value);
+    cat_snprintf(c, sizeof(c), "%s%d",
+	         dir_get_tileset_name(cardinal_tileset_dirs[i]), value);
   }
 
   return c;
@@ -1129,8 +1129,8 @@
   for (i = 0; i < num_valid_tileset_dirs; i++) {
     int value = (index >> i) & 1;
 
-    snprintf(c + strlen(c), sizeof(c) - strlen(c), "%s%d",
-	     dir_get_tileset_name(valid_tileset_dirs[i]), value);
+    cat_snprintf(c, sizeof(c), "%s%d",
+	         dir_get_tileset_name(valid_tileset_dirs[i]), value);
   }
 
   return c;
Index: common/aicore/cm.c
===================================================================
--- common/aicore/cm.c	(revision 12680)
+++ common/aicore/cm.c	(working copy)
@@ -2012,10 +2012,10 @@
 {
   int nout;
 
-  nout = snprintf(buffer, bufsz, "[%d %d %d %d %d %d]",
-		  production[FOOD], production[SHIELD],
-		  production[TRADE], production[GOLD],
-		  production[LUXURY], production[SCIENCE]);
+  nout = my_snprintf(buffer, bufsz, "[%d %d %d %d %d %d]",
+		     production[FOOD], production[SHIELD],
+		     production[TRADE], production[GOLD],
+		     production[LUXURY], production[SCIENCE]);
 
   assert(nout >= 0 && nout <= bufsz);
 }
@@ -2069,8 +2069,8 @@
   freelog(loglevel, "tiles used:");
   for (i = 0; i < num_types(state); i++) {
     if (soln->worker_counts[i] != 0) {
-      snprintf(buf, sizeof(buf),
-          "  %d tiles of type ", soln->worker_counts[i]);
+      my_snprintf(buf, sizeof(buf),
+                  "  %d tiles of type ", soln->worker_counts[i]);
       print_tile_type(loglevel, tile_type_get(state, i), buf);
     }
   }
Index: configure.ac
===================================================================
--- configure.ac	(revision 12680)
+++ configure.ac	(working copy)
@@ -320,18 +320,6 @@
   LIBS="$LIBS -lwsock32"
 fi
 
-dnl Check libUTF8
-AC_ARG_WITH(libutf8,
-            AC_HELP_STRING([--with-libutf8],
-               [Use the libutf8 library (needed for some systems)]),
-            [with_libutf8=$withval], [with_libutf8=no])
-if test "$MINGW32" = yes || test "$with_libutf8" = yes; then
-  AC_CHECK_HEADER(libutf8.h, [],
-                  AC_MSG_ERROR([Could not find libutf8 library (libutf8.h)]))
-  AC_DEFINE(HAVE_LIBUTF8_H, 1, [Use libutf8's stdio functions])
-  LIBS="$LIBS -lutf8"
-fi
-
 dnl Check for zlib (needed for libpng)
 AC_CHECK_LIB(z, gzgets, , 
   AC_MSG_ERROR([Could not find zlib library.]), )
@@ -483,7 +471,7 @@
   dnl Want to get appropriate -I flags:
   fc_save_CPPFLAGS="$CPPFLAGS"
   CPPFLAGS="$CPPFLAGS $CLIENT_CFLAGS"
-  AC_CHECK_HEADER(X11/xpm.h, , 
+  AC_CHECK_HEADER(X11/xpm.h, ,
     AC_MSG_ERROR(need X11/xpm.h header; perhaps try/adjust --with-xpm-include))
   CPPFLAGS="$fc_save_CPPFLAGS"
 fi
@@ -499,11 +487,16 @@
 AC_FUNC_FORK
 AC_FUNC_STRCOLL
 AC_FUNC_VPRINTF
+
+dnl Windows vsnprintf doesn't support argument reordering (see PR#12932)
+if test "x$MINGW32" != "xyes"; then
 AC_FUNC_VSNPRINTF
+AC_CHECK_FUNCS([vsnprintf])
+fi
 
 AC_CHECK_FUNCS([fileno ftime gethostname getpwuid inet_aton \
 		select snooze strerror strcasecmp strncasecmp \
-		strlcat strlcpy strstr usleep vsnprintf uname flock \
+		strlcat strlcpy strstr usleep uname flock \
 		gethostbyname connect bind])
 
 AC_MSG_CHECKING(for working gettimeofday)
Index: manual/civmanual.c
===================================================================
--- manual/civmanual.c	(revision 12680)
+++ manual/civmanual.c	(working copy)
@@ -114,7 +114,7 @@
   for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
     int i;
 
-    snprintf(filename, sizeof(filename), "manual%d.html", manuals + 1);
+    my_snprintf(filename, sizeof(filename), "manual%d.html", manuals + 1);
 
     if (!is_reg_file_for_access(filename, TRUE)
         || !(doc = fopen(filename, "w"))) {
Index: utility/ftwl/common_types.c
===================================================================
--- utility/ftwl/common_types.c	(revision 12680)
+++ utility/ftwl/common_types.c	(working copy)
@@ -287,8 +287,8 @@
 {
   static char buffer[100];
 
-  snprintf(buffer, 100, "{x=%d, y=%d, width=%d, height=%d}", rect->x,
-	   rect->y, rect->width, rect->height);
+  my_snprintf(buffer, 100, "{x=%d, y=%d, width=%d, height=%d}", rect->x,
+	      rect->y, rect->width, rect->height);
   return buffer;
 }
 
@@ -466,7 +466,7 @@
   static char out[100];
   char buffer[100];
   if (key->type == BE_KEY_NORMAL) {
-    snprintf(buffer, sizeof(buffer), "%c", key->key);
+    my_snprintf(buffer, sizeof(buffer), "%c", key->key);
   } else {
     int i;
     bool found = FALSE;
@@ -481,10 +481,10 @@
     assert(found);
   }
 
-  snprintf(out, sizeof(out), "%s%s%s%s",
-	   (key->alt ? "Alt-" : ""),
-	   (key->control ? "Ctrl-" : ""),
-	   (key->shift ? "Shift-" : ""), buffer);
+  my_snprintf(out, sizeof(out), "%s%s%s%s",
+	     (key->alt ? "Alt-" : ""),
+	     (key->control ? "Ctrl-" : ""),
+	     (key->shift ? "Shift-" : ""), buffer);
   return out;
 }
 
Index: utility/support.h
===================================================================
--- utility/support.h	(revision 12680)
+++ utility/support.h	(working copy)
@@ -26,9 +26,6 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
-#ifdef HAVE_LIBUTF8_H
-#include <libutf8.h>
-#endif
 
 #include "shared.h"		/* bool type and fc__attribute */
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to