Commit b99692db authored by Federico Mena Quintero's avatar Federico Mena Quintero
Browse files

(#276) - Guard against getting a cairo_t in an error state at the toplevel API

The cairo-dock program was passing a cairo_t in an error state to
rsvg_handle_render_cairo(), and so we failed deep in the innards of
librsvg when cairo-rs validates the cairo::Context's status.

Cairo-dock was doing something like

  surf = cairo_image_surface_create (... an invalid size ...);
  cr = cairo_create (surf);

  rsvg_handle_render_cairo (handle, cr);    // we now catch the error right here

We catch invalid cr's, emit a warning, and return FALSE from

parent 15711ddd
Pipeline #13938 failed with stages
in 17 minutes and 51 seconds
......@@ -224,16 +224,27 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
RsvgDrawingCtx *draw;
RsvgNode *drawsub = NULL;
cairo_status_t status;
g_return_val_if_fail (handle != NULL, FALSE);
if (handle->priv->state != RSVG_HANDLE_STATE_CLOSED_OK)
return FALSE;
status = cairo_status (cr);
if (status != CAIRO_STATUS_SUCCESS) {
g_warning ("cannot render on a cairo_t with a failure status (status=%d, %s)",
(int) status,
cairo_status_to_string (status));
return FALSE;
if (id && *id)
drawsub = rsvg_defs_lookup (handle->priv->defs, id);
if (drawsub == NULL && id != NULL) {
g_warning ("element id=\"%s\" does not exist", id);
/* todo: there's no way to signal that @id doesn't exist */
return FALSE;
......@@ -465,6 +465,32 @@ dimensions_and_position (void)
g_object_unref (handle);
static void
detects_cairo_context_in_error (void)
if (g_test_subprocess ()) {
char *filename = get_test_filename ("example.svg");
GError *error = NULL;
RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
g_assert (handle != NULL);
g_assert (error == NULL);
/* this is wrong; it is to simulate creating a surface and a cairo_t in error */
cairo_surface_t *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, -1, -1);
cairo_t *cr = cairo_create (surf);
/* rsvg_handle_render_cairo() should return FALSE when it gets a cr in an error state */
g_assert (!rsvg_handle_render_cairo (handle, cr));
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_failed ();
g_test_trap_assert_stderr ("*WARNING*cannot render on a cairo_t with a failure status*");
main (int argc, char **argv)
......@@ -491,6 +517,7 @@ main (int argc, char **argv)
g_test_add_func ("/api/handle_get_pixbuf", handle_get_pixbuf);
g_test_add_func ("/api/handle_get_pixbuf_sub", handle_get_pixbuf_sub);
g_test_add_func ("/api/dimensions_and_position", dimensions_and_position);
g_test_add_func ("/api/detects_cairo_context_in_error", detects_cairo_context_in_error);
return g_test_run ();
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment