GNOME Bugzilla – Bug 351034
vasnprint aborts with large %I64x values
Last modified: 2006-08-20 13:41:24 UTC
Steps to reproduce: 1. call g_vsnprintf with %I64 format and single __uint64 with value > 2^32 2. 3. Stack trace: Other information: Test program (thanks to Joerg Mayer) below, followed by proposed patch to vasnprintf.c /* Testprogram for http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1025 * * Compile with: * gcc -Wall `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0` -o gtest64 gtest64.c * which expands on my system to * gcc -Wall -I/opt/gnome/include/glib-2.0 -I/opt/gnome/lib/glib-2.0/include -L/opt/gnome/lib -lglib-2.0 -o gtest64 gtest64.c * Finally, run with ./gtest64 or something like that. */ #include <glib.h> #include <glib/gprintf.h> /* Formats for printing 64-bit unsigned hexadecimal numbers */ #ifndef PRIx64 #ifdef _MSC_EXTENSIONS #define PRIx64 "I64x" #else /* _MSC_EXTENSIONS */ #define PRIx64 "llx" #endif /* _MSC_EXTENSIONS */ #endif /* PRIx64 */ #define BUFLEN 100 char buffer[BUFLEN]; guint64 test1 = G_GINT64_CONSTANT(0x11223344U); guint64 test2 = G_GINT64_CONSTANT(0x11223344556677U); guint64 test3 = G_GINT64_CONSTANT(0x1122334455667788U); guint64 test4 = G_GINT64_CONSTANT(0xFFEEDDCC11223344U); void printit(const char *format, ...) { va_list ap; va_start(ap, format); g_vsnprintf(buffer, BUFLEN, format, ap); g_printf("%s\n", buffer); va_end(ap); } int main() { printit("Test1: %" PRIx64 , test1); printit("Test2: %" PRIx64 , test2); printit("Test3: %" PRIx64 , test3); printit("Test4: %" PRIx64 , test4); return 0; } Proposed patch: --- vasnprintf.c.orig 2004-05-14 05:58:19.000000000 +0100 +++ vasnprintf.c 2006-08-12 12:26:39.234375000 +0100 @@ -480,6 +480,16 @@ + 2; /* account for leading sign or alternate form */ else # endif +# ifdef HAVE_INT64_AND_I64 + if (type == TYPE_INT64 || type == TYPE_UINT64) + tmp_length = + (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else +# endif if (type == TYPE_LONGINT || type == TYPE_ULONGINT) tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT
Thanks. Embarrassing bug. Fix committed to glib-2-10 and HEAD: 2006-08-20 Tor Lillqvist <tml@novell.com> * glib/gnulib/vasnprintf.c (vasnprintf): Fix crash when printing large 64-bit values on Win32 using the %I64x format. (#351034, Neil Piercy)