Bug 689547 - bad params to XInitImage on large bitmaps
Summary: bad params to XInitImage on large bitmaps
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: X Display Driver (show other bugs)
Version: master
Hardware: PC Linux
: P4 normal
Assignee: Ralph Giles
URL:
Keywords:
: 689561 (view as bug list)
Depends on:
Blocks:
 
Reported: 2007-11-03 09:39 UTC by Russ Cox
Modified: 2009-07-28 09:54 UTC (History)
2 users (show)

See Also:
Customer:
Word Size: ---


Attachments
pprof.ps - local copy of the sample file (102.34 KB, application/postscript)
2009-04-21 15:54 UTC, Alex Cherepanov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Russ Cox 2007-11-03 09:39:39 UTC
On large bitmaps, calls to XInitImage fail, producing an /unknownerror in
builtin ops like fill or show.  For example, if you run gv on
http://pdos.csail.mit.edu/~rsc/pprof.ps, it dies with the gs error:

Error: /unknownerror in --fill--
Operand stack:
   --nostringval--
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--  
--nostringval--   2   %stopped_push   --nostringval--   --nostringval--  
--nostringval--   false   1   %stopped_push   1905   1   3   %oparray_pop   1904
  1   3   %oparray_pop   1888   1   3   %oparray_pop   1771   1   3  
%oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--  
--nostringval--   --nostringval--   2   %stopped_push   --nostringval--
Dictionary stack:
   --dict:1124/1684(ro)(G)--   --dict:0/20(G)--   --dict:71/200(L)--  
--dict:36/200(L)--
Current allocation mode is local
GPL Ghostscript SVN PRE-RELEASE 8.61: Unrecoverable error, exit code 1

Alternately, you can load almost any PostScript file and zoom in to scale 4x or
8x or 10x.  All that matters is that the image bitmap for the entire page is
very wide.

I have tracked down the problem, and it appears to be a bad interaction between
gs and recent sanity checking in the X library.

In particular, sometimes x_copy_image in gdevx.c gets called with wide widths
but narrow raster values.  Even though the raster is apparently wrong, the X
graphics operations would work okay with that value.  But new versions of X11
have various checks in XInitImage, one of which is that the raster is greater
than or equal to the width of the image times the depth.

To see that this diagnosis is correct, replacing the call to XInitImage with a
call to _XInitImageFuncPtrs (which is just XInitImage without the sanity
checking) makes gs start working.  But of course _XInitImageFuncPtrs is not a
public interface function and thus probably not the best fix.  Replacing the
"bytes_per_line = raster" with "bytes_per_line = 0" (which makes X compute the
value from width and depth) works fine in the zoom levels that would otherwise
crash but causes the previously-working zoom levels to shear the image (or
worse), presumably because the "obvious" raster is not the right one at those
levels.

Also, the new XInitImage also requires bitmap_pad be set always.

The patch below also fixes the problem -- I can run "gv pprof.ps" at all zoom
levels, and I can also zoom into regular documents.  

Perhaps it is not the right fix -- perhaps the actual bug is that x_copy_image
is being called with a bad raster value in the first place.  But it does work.

$ svn diff gdevx.c
Index: gdevx.c
===================================================================
--- gdevx.c	(revision 8346)
+++ gdevx.c	(working copy)
@@ -565,15 +565,24 @@
 	X_SET_FORE_COLOR(xdev, pixel);
 	XDrawPoint(xdev->dpy, xdev->dest, xdev->gc, x, y);
     } else {
-	xdev->image.width = sourcex + w;
+	/* Reduce base, sourcex  */
+	int width = sourcex + w;
+    	int vdepth = xdev->vinfo->depth;
+	xdev->image.width = width;
 	xdev->image.height = h;
 	xdev->image.format = ZPixmap;
 	xdev->image.data = (char *)base;
-	xdev->image.depth = xdev->vinfo->depth;
-	xdev->image.bytes_per_line = raster;
+	xdev->image.depth = vdepth;
+	xdev->image.bitmap_pad = 8;
+	if (width * vdepth < raster * 8)
+	    xdev->image.bytes_per_line = raster;
+	else
+	    xdev->image.bytes_per_line = 0;
 	xdev->image.bits_per_pixel = depth;
-	if (XInitImage(&xdev->image) == 0)
+	if (XInitImage(&xdev->image) == 0){
+	    errprintf("XInitImage failed in x_copy_image.\n");
 	    return_error(gs_error_unknownerror);
+	}
 	XPutImage(xdev->dpy, xdev->dest, xdev->gc, &xdev->image,
 		  sourcex, 0, x, y, w, h);
 	xdev->image.depth = xdev->image.bits_per_pixel = 1;
$
Comment 1 James Cloos 2009-04-21 12:00:03 UTC
Is this the same as bug #689561?
Comment 2 Alex Cherepanov 2009-04-21 15:54:42 UTC
Created attachment 4963 [details]
pprof.ps - local copy of the sample file
Comment 3 Ralph Giles 2009-07-28 09:52:17 UTC
*** Bug 689561 has been marked as a duplicate of this bug. ***
Comment 4 Ralph Giles 2009-07-28 09:54:22 UTC
I don't know if the raster value is wrong either, but the patch certainly does
resolve the issue. Committed as r9898, it will be in the 8.70 release.

Thanks!