summaryrefslogtreecommitdiff
path: root/devices
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2023-03-30 16:30:09 +0100
committerRobin Watts <Robin.Watts@artifex.com>2023-03-31 09:01:53 +0100
commitf3a8e0a36b7bcc6c014e90570e07bb447456cb6b (patch)
tree9dcb77f199779877a56bcde313ec33426c5d4595 /devices
parent7745bc9ed8be0692f798fae8c0d033e948af22dd (diff)
downloadghostpdl-f3a8e0a36b7bcc6c014e90570e07bb447456cb6b.tar.gz
pdfwrite - do not reverse the order of clip subpaths
Bug #706523 "Error during merge Pdf Function : "*** C stack overflow. Quiting..."" The example file uses (on page 10) an enormously complicated clip path. I suspect this was a chroma-keyed image or something similar which has been downgraded by pdfwrite (which produced the original file) to a fill and a complex clip. The code for writing clips in pdfwrite uses a recursive function in order to reverse the order of the subpaths. None of us can see a sane reason for reversing the subpaths, so this commit simply does away with that, which means we don't need the recursion and don't fall foul of highly complex clip paths. (Note on Linux this did not fail, presumably because the C exec stack is larger. But a more complex example presumably would fail) A few PXL files, when converted to PDF and the PDF rendered, show dropouts at low resolution (65 dpi) but these files are already dropping most of the strokes anyway at this resolution so I'm not going to worry about the small difference. A few other files exhibit single pixel differences at higher resolution, but again nothing of concern.
Diffstat (limited to 'devices')
-rw-r--r--devices/vector/gdevpdfd.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c
index fb55655c9..46f49b95c 100644
--- a/devices/vector/gdevpdfd.c
+++ b/devices/vector/gdevpdfd.c
@@ -685,20 +685,23 @@ static int
pdf_put_clip_path_list_elem(gx_device_pdf * pdev, gx_cpath_path_list *e,
gs_path_enum *cenum, gdev_vector_dopath_state_t *state,
gs_fixed_point vs[3])
-{ /* This recursive function provides a reverse order of the list elements. */
+{
int segments = 0;
- if (e->next != NULL) {
- int code = pdf_put_clip_path_list_elem(pdev, e->next, cenum, state, vs);
-
- if (code != 0)
- return code;
+ /* This function was previously recursive and reversed the order of subpaths. This
+ * could lead to a C exec stack overflow on sufficiently complex clipping paths
+ * (such as those produced by pdfwrite as a fallback for certain kinds of images).
+ * Writing the subpaths in the forward order avoids the problem, is probably
+ * slightly faster and uses less memory. Bug #706523.
+ */
+ while (e) {
+ segments = pdf_write_path(pdev, cenum, state, &e->path, 0, gx_path_type_clip | gx_path_type_optimize, NULL);
+ if (segments < 0)
+ return segments;
+ if (segments)
+ pprints1(pdev->strm, "%s n\n", (e->rule <= 0 ? "W" : "W*"));
+ e = e->next;
}
- segments = pdf_write_path(pdev, cenum, state, &e->path, 0, gx_path_type_clip | gx_path_type_optimize, NULL);
- if (segments < 0)
- return segments;
- if (segments)
- pprints1(pdev->strm, "%s n\n", (e->rule <= 0 ? "W" : "W*"));
return 0;
}