Bug 692553 - Exception reading PDF file
Summary: Exception reading PDF file
Status: NOTIFIED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: PDF Interpreter (show other bugs)
Version: 9.04
Hardware: PC All
: P2 normal
Assignee: Michael Vrhel
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-09-28 17:44 UTC by Marcos H. Woehrmann
Modified: 2011-10-11 16:06 UTC (History)
1 user (show)

See Also:
Customer: 384
Word Size: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcos H. Woehrmann 2011-09-28 17:44:31 UTC
The attached PDF files produce exceptions when read by Ghostscript 9.04 under Windows.  The original customer file, 20588799.pdf, has the error on page 19.  I tried simplifying the file by removing pages 20 through 229, see the attached 20588799c.pdf, and now the error occurs on page 8.

I haven't been able to duplicate this with anything other than the Windows 9.04 release; the error does not occur on Linux nor Mac OS X and my Windows compiler installation appears to be broken. 

The command line I'm using:

  gswin32.exe  -sDEVICE=tiffg4 -dPDFFitPage -dSAFER -r300 -o 20588799.tif 20588799.pdf

Note that removing -dPDFFitPage or -dSafer or both causes the error to not occur.
Comment 4 Marcos H. Woehrmann 2011-09-28 22:20:09 UTC
This may be a regression, gs9.01 process the file correctly (I say 'may' since there appears to be an indeterminism in the error, I've had 9.04 fail on different pages with the same input file).
Comment 5 Marcos H. Woehrmann 2011-09-29 01:15:51 UTC
It looks like this may be fixed in master; I'm bisecting now.
Comment 6 Marcos H. Woehrmann 2011-09-29 15:29:20 UTC
Running valgrind on Linux produces some suspicious results:


==5556== Invalid read of size 1
==5556==    at 0x4C28E58: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6de is 2 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556== 
==5556== Invalid read of size 1
==5556==    at 0x4C28E61: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6dd is 3 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556== 
==5556== Invalid read of size 1
==5556==    at 0x4C28E6C: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6dc is 4 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556== 
==5556== Invalid read of size 1
==5556==    at 0x4C28E77: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6db is 5 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556== 
==5556== Invalid read of size 1
==5556==    at 0x4C28EB8: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6da is 6 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556== 
==5556== Invalid read of size 1
==5556==    at 0x4C28ECA: memcpy (mc_replace_strmem.c:497)
==5556==    by 0x9D8D42: fill_threshhold_buffer (gxht_thresh.c:560)
==5556==    by 0x9D91D5: gxht_thresh_plane (gxht_thresh.c:694)
==5556==    by 0x9E3E2C: image_render_mono_ht (gximono.c:1120)
==5556==    by 0x9DB936: gx_image1_plane_data (gxidata.c:209)
==5556==    by 0x9DEC47: gx_image_plane_data_rows (gximage.c:181)
==5556==    by 0x989F0C: gs_image_next_planes (gsimage.c:601)
==5556==    by 0x58C50B: image_file_continue (zimage.c:546)
==5556==    by 0x53DE6C: do_call_operator (interp.c:84)
==5556==    by 0x5402F0: interp (interp.c:1163)
==5556==    by 0x53E617: gs_call_interp (interp.c:490)
==5556==    by 0x53E433: gs_interpret (interp.c:448)
==5556==  Address 0x9f6e6d8 is 8 bytes before a block of size 112 alloc'd
==5556==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==5556==    by 0x991C0F: gs_heap_alloc_bytes (gsmalloc.c:181)
==5556==    by 0x991E85: gs_heap_alloc_byte_array (gsmalloc.c:240)
==5556==    by 0x981E47: gx_ht_construct_threshold (gsht.c:1545)
==5556==    by 0x9D8547: gxht_thresh_image_init (gxht_thresh.c:386)
==5556==    by 0x9E0416: gs_image_class_3_mono (gximono.c:168)
==5556==    by 0x9E7410: gx_image_enum_begin (gxipixel.c:676)
==5556==    by 0x9DFC3E: gx_begin_image1 (gximage1.c:92)
==5556==    by 0xA0F1F1: gx_default_begin_typed_image (gdevddrw.c:1029)
==5556==    by 0xA0F08E: gx_default_begin_image (gdevddrw.c:994)
==5556==    by 0xA0F197: gx_default_begin_typed_image (gdevddrw.c:1021)
==5556==    by 0x988DAB: gs_image_begin_typed (gsimage.c:240)
==5556==
Comment 8 Marcos H. Woehrmann 2011-09-29 19:10:00 UTC
Running git bisect on Windows XP says that the issue first appeared in commit 8024d7db.  

I'm not 100% confident in this analysis, since the page number on which the error occurs moves around with later commits.
Comment 9 Marcos H. Woehrmann 2011-09-29 19:21:04 UTC
(In reply to comment #5)
> It looks like this may be fixed in master; I'm bisecting now.

This statement is not correct; master fails on page 60 for me.
Comment 10 Robin Watts 2011-10-03 12:25:58 UTC
I can reproduce the problem on 32bit windows XP, using HEAD but not in the debug configuration.

Instead, build the 'release' or 'profile' configurations (profile being more useful as it retains at least some debugging information).

image_render_mono_ht calls gxht_thresh_plane. At line 694 this calls fill_threshold_buffer. That immediately calls memcpy, and this crashes.

The output from some debugging is as follows:

Page 43
threshold=fb7020
d_order->threshold=fb7020
yci=-21
penum->dev->band_offset_y=0
thresh_height=8
dy=-5
k=0
vdi=3530
pos=0
thresh_tile=fb6ff8
dx=0
lw=8
nft=264
rtw=6

thresh_tile points to unreadable memory (8 bytes before a defined block)

So, the problem appears to be in the calculation of dy - specifically I don't think the code ever expects to get -ve numbers.
Comment 11 Robin Watts 2011-10-03 12:28:46 UTC
@@ -686,6 +688,8 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order
             for (k = 0; k < vdi; k++) {
                 /* Get a pointer to our tile row */
                 dy = (penum->yci + k + penum->dev->band_offset_y) % thresh_height;
+                if (dy < 0)
+                    dy += thresh_height;
                 thresh_tile = threshold + d_order->width * dy;
                 /* Fill the buffer, can be multiple rows.  Make sure
                    to update with stride */

Should fix it (and indeed does seem to here). I'll leave this to Michael to commit in case I am patching a symptom rather than a cause.
Comment 12 Robin Watts 2011-10-03 16:20:33 UTC
Confirmed with Michael, and committed as:

commit e776cc41b9da0a535adde126464d6af906b082ae
Author: Robin Watts <Robin.Watts@artifex.com>
Date:   Mon Oct 3 17:15:53 2011 +0100

    Fix for Bug 692553; SEGV in fast thresholding halftoning code.

    Stupid C got the % operation wrong.

    In this instance, it gives an unexpected negative value causing out of
    bounds offsets. Simple fix is to offset by the period if it's negative.