Package: gnome-session
Version: 2.18.2-1
Severity: important
Tags: patch

Since the upgrade to 2.18, I had been plagued by gnome-session hanging
on startup of any 'non-trivial' session. Attaching gdb showed the hang
to be a deadlock because it crashed somewhere inside the glibc memory
management code, and the signal handler tried to use memory management
functions as well, so it hung waiting for the glibc internal memory
management mutex.

After a long debugging session chasing countless red herrings, I finally
tracked down the cause of the crash. update_trans_effect could end up
using stale icon dimensions, so it would write beyond the end of the
memory allocated for the pixel data. The attached patch fixes this.


--- System information. ---
Architecture: powerpc
Kernel:       Linux 2.6.21-1-powerpc

Debian Release: lenny/sid
  500 unstable        mirror.switch.ch 
  500 stable          security.debian.org 
  102 experimental    ftp.ch.debian.org 

--- Package information. ---
Depends                      (Version) | Installed
======================================-+-==============
libatk1.0-0                (>= 1.13.2) | 1.18.0-2
libbonobo2-0               (>= 2.15.0) | 2.18.0-2
libc6                       (>= 2.5-5) | 2.5-11
libdbus-1-3                  (>= 0.94) | 1.1.1-1
libdbus-glib-1-2             (>= 0.73) | 0.73-2
libesd0                   (>= 0.2.35)  | 
 OR libesd-alsa0           (>= 0.2.35) | 0.2.36-3
libgconf2-4                (>= 2.13.5) | 2.18.0.1-3
libglib2.0-0               (>= 2.12.9) | 2.12.12-1
libgnome-desktop-2         (>= 2.11.1) | 2.18.2-1
libgnome-keyring0             (>= 0.8) | 0.8.1-2
libgnome2-0                (>= 2.17.3) | 2.18.0-4
libgnomeui-0               (>= 2.17.1) | 2.18.1-2
libgtk2.0-0                (>= 2.10.3) | 2.10.13-1
libice6                   (>= 1:1.0.0) | 1:1.0.3-2
liborbit2                (>= 1:2.14.1) | 1:2.14.7-0.1
libpango1.0-0              (>= 1.16.4) | 1.16.4-1
libsm6                                 | 2:1.0.3-1
libwrap0                               | 7.6.dbs-13
libx11-6                               | 2:1.1.2-1
libxau6                                | 1:1.0.3-2
libxrandr2                (>= 2:1.2.0) | 2:1.2.1-1
gconf2                   (>= 2.12.1-1) | 2.18.0.1-3
gnome-control-center       (>= 1:2.18) | 1:2.18.1-1
gnome-control-center       (<< 1:2.19) | 1:2.18.1-1

-- 
Earthling Michel Dänzer           |          http://tungstengraphics.com
Libre software enthusiast         |          Debian, X and DRI developer
--- gnome-session-2.18.2.orig/gnome-session/splash-widget.c	2007-05-28 13:41:45.000000000 +0200
+++ gnome-session-2.18.2/gnome-session/splash-widget.c	2007-06-25 20:34:32.000000000 +0200
@@ -74,13 +74,6 @@ typedef struct {
 typedef struct {
 	SplashWidget *sw;
 	SplashIcon   *si;
-	int width;
-	int height;
-	int n_channels;
-	int rowstride_trans;
-	int rowstride_orig;
-	guchar *pixels_trans;
-	guchar *pixels_orig;
 } TransParam;
 
 static gboolean
@@ -485,6 +478,13 @@ layout_icon (SplashWidget *sw, SplashIco
 			si->scaled = gdk_pixbuf_scale_simple (
 				si->unscaled, sw->icon_size,
 				sw->icon_size, GDK_INTERP_BILINEAR);
+
+		if (!gdk_pixbuf_get_has_alpha (si->scaled)) {
+			si->scaled_copy = gdk_pixbuf_add_alpha (si->scaled, FALSE, 0, 0, 0);
+			g_object_unref (si->scaled);
+			si->scaled = gdk_pixbuf_copy (si->scaled_copy);
+		} else 
+			si->scaled_copy = gdk_pixbuf_copy (si->scaled);
 	}
 
 	if (sw->cur_x_offset >= (sw->image_bounds.width - SPLASH_ICON_BORDER * 2 -
@@ -576,32 +576,19 @@ splash_widget_add_icon (SplashWidget *sw
 		si = g_new0 (SplashIcon, 1);
 		si->unscaled = pb;
 
+		layout_icon (sw, si, &area);
+
 		sw->icons = g_list_append (sw->icons, si);
 
-		layout_icon (sw, si, &area);
-	
 		/* prepare transparency effect */
 		if ((gdk_pixbuf_get_colorspace (si->scaled) == GDK_COLORSPACE_RGB) &&
 		    (gdk_pixbuf_get_bits_per_sample (si->scaled) == 8) &&
 		    (gdk_pixbuf_get_n_channels (si->scaled))) {
 			si->trans_count = 0;
-			if (!gdk_pixbuf_get_has_alpha (si->scaled)) {
-				si->scaled_copy = gdk_pixbuf_add_alpha (si->scaled, FALSE, 0, 0, 0);
-				g_object_unref (si->scaled);
-				si->scaled = gdk_pixbuf_copy (si->scaled_copy);
-			} else 
-				si->scaled_copy = gdk_pixbuf_copy (si->scaled);
 
 			tp = g_new0(TransParam, 1);
 			tp->si = si;
 			tp->sw = sw;
-			tp->width  = gdk_pixbuf_get_width  (tp->si->scaled);
-			tp->height = gdk_pixbuf_get_height (tp->si->scaled);
-			tp->rowstride_trans = gdk_pixbuf_get_rowstride (tp->si->scaled);
-			tp->rowstride_orig  = gdk_pixbuf_get_rowstride (tp->si->scaled_copy);
-			tp->pixels_trans = gdk_pixbuf_get_pixels (tp->si->scaled);
-			tp->pixels_orig  = gdk_pixbuf_get_pixels (tp->si->scaled_copy);
-			tp->n_channels = gdk_pixbuf_get_n_channels (tp->si->scaled);
 
 			gdk_pixbuf_fill (si->scaled, 0x00000000);
 			g_timeout_add (TRANS_TIMEOUT, update_trans_effect, tp);
@@ -624,6 +611,13 @@ update_trans_effect (gpointer trans_para
 	gdouble    r_mul, g_mul, b_mul, a_mul;
 	gint       x = 0;
 	gint	   y = 0;
+	gint	   width = 0;
+	gint	   height = 0;
+	int	   n_channels;
+	int	   rowstride_trans;
+	int	   rowstride_orig;
+	guchar	   *pixels_trans;
+	guchar	   *pixels_orig;
 
 	TransParam *tp = (TransParam *) trans_param;
 
@@ -645,10 +639,18 @@ update_trans_effect (gpointer trans_para
 	g_mul = 1;
 	b_mul = 1;
 
-	for (y = 0; y < tp->height; y++) {
-		for (x = 0; x < tp->width; x++) {
-			p_trans = tp->pixels_trans + y * tp->rowstride_trans + x * tp->n_channels;
-			p_orig  = tp->pixels_orig  + y * tp->rowstride_orig  + x * tp->n_channels;
+	rowstride_trans = gdk_pixbuf_get_rowstride (tp->si->scaled);
+	rowstride_orig  = gdk_pixbuf_get_rowstride (tp->si->scaled_copy);
+	pixels_trans = gdk_pixbuf_get_pixels (tp->si->scaled);
+	pixels_orig  = gdk_pixbuf_get_pixels (tp->si->scaled_copy);
+	n_channels = gdk_pixbuf_get_n_channels (tp->si->scaled);
+	width  = gdk_pixbuf_get_width  (tp->si->scaled);
+	height = gdk_pixbuf_get_height (tp->si->scaled);
+
+	for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+			p_trans = pixels_trans + y * rowstride_trans + x * n_channels;
+			p_orig  = pixels_orig  + y * rowstride_orig  + x * n_channels;
 
 			/* we can add more effects here apart from alpha fading */
 			p_trans[0] = r_mul * p_orig[0];

Reply via email to