Package: xsane
Version: 0.995-3
Severity: normal
Tags: patch

The problem occurs in xsane when accessing an epson/epkowa driver through
the network backend.  Trying to change options like binary/gray/color,
resolutions, etc., in xsane results in a dialog box with 'Failed to set
value of option mode: invalid argument'.  Playing with various controls
for a while (and dismissing the errors) eventually results in the problem
"fixing itself," after which xsane behaves normally.  There are no problems
when accessing the same driver directly (ie. xsane + epson backend on the
same host).

Please note that this is the same bug referenced here:
  <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=307088>
It was reassigned from xsane to libsane by Julien quite some time ago.
>From what I found, I think it really is a bug in xsane.  (xsane assumes a
memory structure is static but this is not guaranteed when the network
backend is used.)

Here's what I discovered.  A patch that fixes (or is at least an effective
work-around) is attached.

The xsane frontend talks to the local net backend.  The net backend
communicates with the real (epson) backend over the network and builds
a local copy of an opt structure describing the scanner.  xsane then
constructs its menus by walking this structure and creating gtk_menu
objects with label strings stored as direct pointers into the opt
structure.

Unfortunately, while the opt structure is built once and is then stable on
the remote (epson, epkowa, whatever) backend, that memory space is NOT
stable with the net backend.  The pointer returned by the 'opt =
xsane_get_option_descriptor()' call in xsane.c seems to point to a
general purpose memory buffer used by the sanei_* network routines used
by the net backend.

The end result is that it is a bit of a crap-shoot whether
menu_items[].label (a pointer into the opt structure) still points to the
same string as it did when the menu was created.  Since the label string is
used to request changes to the epson backend configuration by name, the
change request only works if the memory hasn't been overwritten by
something else.

The patch fixes this problem by making a copy of the option name and
setting menu_items[].label to point to the new string (removing xsane's
dependence on a volatile memory structure).

See the patch for additional comments.

-- Brad

-- System Information:
Debian Release: 4.0
  APT prefers stable
  APT policy: (900, 'stable'), (80, 'unstable'), (60, 'experimental')
Architecture: amd64 (x86_64)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.25.6
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)

Versions of packages xsane depends on:
ii  libatk1.0-0            1.12.4-3          The ATK accessibility toolkit
ii  libc6                  2.3.6.ds1-13etch5 GNU C Library: Shared libraries
ii  libcairo2              1.2.4-4.1+etch1   The Cairo 2D vector graphics libra
ii  libfontconfig1         2.4.2-1.2         generic font configuration library
ii  libgimp2.0             2.2.13-1etch4     Libraries necessary to Run the GIM
ii  libglib2.0-0           2.12.4-2          The GLib library of C routines
ii  libgtk2.0-0            2.8.20-7          The GTK+ graphical user interface 
ii  libieee1284-3          0.2.10-4          cross-platform library for paralle
ii  libjpeg62              6b-13             The Independent JPEG Group's JPEG 
ii  liblcms1               1.15-1            Color management library
ii  libpango1.0-0          1.14.8-5          Layout and rendering of internatio
ii  libpng12-0             1.2.15~beta5-1    PNG library - runtime
ii  libsane                1.0.18-5          API library for scanners
ii  libtiff4               3.8.2-7           Tag Image File Format (TIFF) libra
ii  libusb-0.1-4           2:0.1.12-5        userspace USB programming library
ii  libx11-6               2:1.0.3-7         X11 client-side library
ii  libxcursor1            1.1.7-4           X cursor management library
ii  libxext6               1:1.0.1-2         X11 miscellaneous extension librar
ii  libxfixes3             1:4.0.1-5         X11 miscellaneous 'fixes' extensio
ii  libxi6                 1:1.0.1-4         X11 Input extension library
ii  libxinerama1           1:1.0.1-4.1       X11 Xinerama extension library
ii  libxrandr2             2:1.1.0.2-5       X11 RandR extension library
ii  libxrender1            1:0.9.1-3         X Rendering Extension client libra
ii  xsane-common           0.995-3           featureful graphical frontend for 
ii  zlib1g                 1:1.2.3-13        compression library - runtime

-- no debconf information
diff -Bburp -x '*.o' -x '*.swp' xsane-0.995/src/xsane-front-gtk.c xsane-0.995.patched/src/xsane-front-gtk.c
--- xsane-0.995/src/xsane-front-gtk.c	2007-05-17 09:35:06.000000000 -0400
+++ xsane-0.995.patched/src/xsane-front-gtk.c	2008-06-01 02:15:51.000000000 -0400
@@ -1024,6 +1033,10 @@ void xsane_option_menu_new(GtkWidget *pa
   }
 
   menu_items = malloc((num_items + 1) * sizeof(menu_items[0]));
+  if(menu_items == NULL) {
+    DBG (1, "out of memory (line %d)\n", __LINE__);
+    exit(SANE_STATUS_NO_MEM);
+  }
 
   menu = gtk_menu_new();
   if (widget_name)
@@ -1047,11 +1060,38 @@ void xsane_option_menu_new(GtkWidget *pa
 
     gtk_widget_show(item);
 
-    menu_items[i].label = str_list[i];
+    /* The net backend seems to scramble then reconstruct the opt structure
+     * that *str_list points to.  menu_items[].label used to a pointer to
+     * something that then gets changed behind its back.
+     * Let's make a copy of the string.  The 255 max length is a backstop in
+     * case there is a problem with the structure.
+     *
+     * FIXME: This is probably a memory leak.  The same menu seems to be
+     * (re-)generated in response to various user actions.  If gtk did the
+     * appropriate free()'s then presumably the *str_list var would have been
+     * destroyed even without the net backend's help.
+     *
+     * FIXME?: The sanei_* net backend is AFAICT undocumented and a real maze.
+     * I have no idea if the opt structure is supposed to be stable over the
+     * net backend...  Maybe there is a bug there?
+     */
+
+     /* menu_items[i].label = str_list[i]; */
+    menu_items[i].label = strndup(str_list[i], 255);
+    if (menu_items[i].label == NULL || strlen(menu_items[i].label) == 255) {
+      fprintf(stderr, "(xsane_option_menu(): menu item too long: '%s'\n", menu_items[i].label);
+      exit(SANE_STATUS_NO_MEM);
+    }
+
     menu_items[i].elem  = elem;
     menu_items[i].index = i;
+    DBG(DBG_proc, "\tmenu_item->%p\tindex=%d\n\tlabel='%s'\n\tmenu_item=%s\n", 
+        menu_items+i,
+        i,
+        str_list[i],
+        menu_items[i].label
+        );
   }
-
   /* add empty element as end of list marker */
   menu_items[i].label = NULL;
   menu_items[i].elem  = NULL;

Reply via email to