After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 577137 - g_logv() will crash if given format args and multiple log levels
g_logv() will crash if given format args and multiple log levels
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
2.18.x
Other NetBSD
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2009-03-28 22:49 UTC by Wim Lewis
Modified: 2009-03-29 19:12 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Wim Lewis 2009-03-28 22:49:58 UTC
On NetBSD/macppc, if you call g_log() with multiple log levels *and* with a log message format string that has arguments (%s or whatever), it will crash.

It looks like the problem is that g_logv() will use its va_list more than once without calling va_copy(). On many ppc systems this fails because va_list is defined as

 struct {
   stuff...
 } va_list[1];

meaning that it is, in effect, passed by reference in cases where an i386's simple pointer-to-the-stack va_list would be passed by value. As a result, the second invocation of *vprintf() picks up where the previous one left off, instead of starting at the beginning.

Using va_copy() will portably make an independent copy of the va_list state, though.

On the other hand, it doesn't look like g_logv() actually *needs* to traverse the argument list more than once: instead of calling *vprintf() for each log level, it could call it just once and use the resulting string for each log message.

Here's a short program demonstrating the crash. Notice how it prints the message from the first of the multiple log levels, but fails trying to format it again for the next log level.

$ cat ./valog2.c

#include <glib.h>

int main()
{
  int foo1 = 42;
  char *foo2 = "fortytwo";
  char *foo3 = "blah";

  g_log("wargha", G_LOG_LEVEL_INFO, "A message at only one log level (%d %s %s)", foo1, foo2, foo3);
 
  g_log("wargha", G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE,
        "A message at multiple log levels (%d %s %s)", foo1, foo2, foo3);
}
$ cc valog2.c `/usr/pkg/bin/pkg-config glib-2.0 --cflags --libs`
$ ./a.out
wargha-INFO: A message at only one log level (42 fortytwo blah)
wargha-INFO: A message at multiple log levels (42 fortytwo blah)
[2]   Segmentation fault (core dumped) ./a.out
$ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "powerpc--netbsd"...(no debugging symbols found)

(gdb) run
Starting program: /home/wiml/bad_glib/a.out 
wargha-INFO: A message at only one log level (42 fortytwo blah)
wargha-INFO: A message at multiple log levels (42 fortytwo blah)

Program received signal SIGSEGV, Segmentation fault.
0xefea53a8 in strlen () from /usr/lib/libc.so.12
(gdb) bt
  • #0 strlen
    from /usr/lib/libc.so.12
  • #1 __vfprintf_unlocked
    from /usr/lib/libc.so.12
  • #2 vasprintf
    from /usr/lib/libc.so.12
  • #3 IA__g_vasprintf
    at gprintf.c line 315
  • #4 IA__g_strdup_vprintf
    at gstrfuncs.c line 218
  • #5 IA__g_logv
    at gmessages.c line 472
  • #6 IA__g_log
    at gmessages.c line 517
  • #7 main

Comment 1 Ryan Niebur 2009-03-29 17:37:29 UTC
On Debian this happens on s930 and powerpc when trying to run the tests that come with the perl Glib. The other architectures worked fine.
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=520484
Comment 2 Matthias Clasen 2009-03-29 19:12:14 UTC
2009-03-29  Matthias Clasen  <mclasen@redhat.com>

        Bug 577137 – g_logv() will crash if given format args and multiple
        log levels

        * glib/gmessages.c (g_logv): Copy a va_list when using it
        multiple times. Reported by Wim Lewis.