summaryrefslogtreecommitdiff
path: root/src/cairo-ps-surface.c
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2017-11-09 20:52:36 +1030
committerAdrian Johnson <ajohnson@redneon.com>2017-11-09 22:02:05 +1030
commitf7d6d78f9428c6813e79d5f7c1351c354d44da64 (patch)
treedc26b71cd0f32ffe546bc57f421b5df738496bf5 /src/cairo-ps-surface.c
parent71746c37d48a08d56b18d4d82185896ada215194 (diff)
downloadcairo-f7d6d78f9428c6813e79d5f7c1351c354d44da64.tar.gz
ps: prevent self-copy infinite loop
Diffstat (limited to 'src/cairo-ps-surface.c')
-rw-r--r--src/cairo-ps-surface.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index fe09ed663..154c854b0 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1216,6 +1216,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
_cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_setup_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *));
+ _cairo_array_init (&surface->recording_surf_stack, sizeof (unsigned int));
surface->num_forms = 0;
surface->forms = _cairo_hash_table_create (_cairo_ps_form_equal);
@@ -1826,6 +1827,8 @@ CLEANUP:
free (comments[i]);
_cairo_array_fini (&surface->dsc_page_setup_comments);
+ _cairo_array_fini (&surface->recording_surf_stack);
+
_cairo_surface_clipper_reset (&surface->clipper);
return status;
@@ -1920,7 +1923,7 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (
cairo_surface_get_device_offset (surf, x_offset, y_offset);
*source_surface = surf;
} else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
- cairo_surface_t *surf;
+ cairo_surface_t *surf = NULL;
*source_surface = ((cairo_surface_pattern_t *) pattern)->surface;
surf = *source_surface;
@@ -1937,6 +1940,8 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (
*x_offset = -sub->extents.x;
*y_offset = -sub->extents.y;
}
+
+ cairo_surface_destroy (surf);
} else if (surf->type != CAIRO_SURFACE_TYPE_IMAGE) {
cairo_image_surface_t *image;
void *image_extra;
@@ -3334,6 +3339,21 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
cairo_surface_clipper_t old_clipper;
cairo_int_status_t status;
cairo_surface_t *free_me = NULL;
+ unsigned int id;
+ int i, recording_surf_stack_size;
+
+ /* Prevent infinite recursion if the recording_surface references a recording
+ * currently being emitted */
+ recording_surf_stack_size = _cairo_array_num_elements (&surface->recording_surf_stack);
+ for (i = 0; i < recording_surf_stack_size; i++) {
+ _cairo_array_copy_element (&surface->recording_surf_stack, i, &id);
+ if (id == recording_surface->unique_id)
+ return CAIRO_STATUS_SUCCESS;
+ }
+ id = recording_surface->unique_id;
+ status = _cairo_array_append (&surface->recording_surf_stack, &id);
+ if (unlikely (status))
+ return status;
if (_cairo_surface_is_snapshot (recording_surface))
free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
@@ -3406,6 +3426,8 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
&surface->cairo_to_ps);
cairo_surface_destroy (free_me);
+ _cairo_array_truncate (&surface->recording_surf_stack, recording_surf_stack_size);
+
return status;
}