From 6cfaab12c70cd4a34c4730837f1ecdf792593c90 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 7 Oct 2015 07:57:39 +0200 Subject: [PATCH] state: Look up clip path lazily Upstream-status: Backport supporting patch https://git.gnome.org/browse/librsvg/commit/rsvg-styles.c?id=6cfaab12c70cd4a34c4730837f1ecdf792593c90 CVE: CVE-2015-7558 Signed-off-by: Armin Kuster --- rsvg-cairo-draw.c | 56 +++++++++++++++++++++++++++++++++---------------------- rsvg-mask.c | 17 ----------------- rsvg-mask.h | 2 -- rsvg-styles.c | 10 +++++++--- rsvg-styles.h | 2 +- 5 files changed, 42 insertions(+), 45 deletions(-) Index: librsvg-2.40.10/rsvg-cairo-draw.c =================================================================== --- librsvg-2.40.10.orig/rsvg-cairo-draw.c +++ librsvg-2.40.10/rsvg-cairo-draw.c @@ -461,7 +461,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * return; need_tmpbuf = ((state->fill != NULL) && (state->stroke != NULL) && state->opacity != 0xff) - || state->clip_path_ref || state->mask || state->filter + || state->clip_path || state->mask || state->filter || (state->comp_op != CAIRO_OPERATOR_OVER); if (need_tmpbuf) @@ -708,18 +708,6 @@ rsvg_cairo_generate_mask (cairo_t * cr, } static void -rsvg_cairo_push_early_clips (RsvgDrawingCtx * ctx) -{ - RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); - - cairo_save (render->cr); - if (rsvg_current_state (ctx)->clip_path_ref) - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == userSpaceOnUse) - rsvg_cairo_clip (ctx, rsvg_current_state (ctx)->clip_path_ref, NULL); - -} - -static void rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx) { /* XXX: Untested, probably needs help wrt filters */ @@ -731,9 +719,27 @@ rsvg_cairo_push_render_stack (RsvgDrawin RsvgState *state = rsvg_current_state (ctx); gboolean lateclip = FALSE; - if (rsvg_current_state (ctx)->clip_path_ref) - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == objectBoundingBox) - lateclip = TRUE; + if (rsvg_current_state (ctx)->clip_path) { + RsvgNode *node; + node = rsvg_defs_lookup (ctx->defs, rsvg_current_state (ctx)->clip_path); + if (node && RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CLIP_PATH) { + RsvgClipPath *clip_path = (RsvgClipPath *) node; + + switch (clip_path->units) { + case userSpaceOnUse: + rsvg_cairo_clip (ctx, clip_path, NULL); + break; + case objectBoundingBox: + lateclip = TRUE; + break; + + default: + g_assert_not_reached (); + break; + } + + } + } if (state->opacity == 0xFF && !state->filter && !state->mask && !lateclip && (state->comp_op == CAIRO_OPERATOR_OVER) @@ -774,7 +780,9 @@ rsvg_cairo_push_render_stack (RsvgDrawin void rsvg_cairo_push_discrete_layer (RsvgDrawingCtx * ctx) { - rsvg_cairo_push_early_clips (ctx); + RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); + + cairo_save (render->cr); rsvg_cairo_push_render_stack (ctx); } @@ -783,14 +791,18 @@ rsvg_cairo_pop_render_stack (RsvgDrawing { RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); cairo_t *child_cr = render->cr; - gboolean lateclip = FALSE; + RsvgClipPath *lateclip = NULL; cairo_surface_t *surface = NULL; RsvgState *state = rsvg_current_state (ctx); gboolean nest; - if (rsvg_current_state (ctx)->clip_path_ref) - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == objectBoundingBox) - lateclip = TRUE; + if (rsvg_current_state (ctx)->clip_path) { + RsvgNode *node; + node = rsvg_defs_lookup (ctx->defs, rsvg_current_state (ctx)->clip_path); + if (node && RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CLIP_PATH + && ((RsvgClipPath *) node)->units == objectBoundingBox) + lateclip = (RsvgClipPath *) node; + } if (state->opacity == 0xFF && !state->filter && !state->mask && !lateclip && (state->comp_op == CAIRO_OPERATOR_OVER) @@ -820,7 +832,7 @@ rsvg_cairo_pop_render_stack (RsvgDrawing nest ? 0 : render->offset_y); if (lateclip) - rsvg_cairo_clip (ctx, rsvg_current_state (ctx)->clip_path_ref, &render->bbox); + rsvg_cairo_clip (ctx, lateclip, &render->bbox); cairo_set_operator (render->cr, state->comp_op); Index: librsvg-2.40.10/rsvg-mask.c =================================================================== --- librsvg-2.40.10.orig/rsvg-mask.c +++ librsvg-2.40.10/rsvg-mask.c @@ -102,23 +102,6 @@ rsvg_get_url_string (const char *str) return NULL; } -RsvgNode * -rsvg_clip_path_parse (const RsvgDefs * defs, const char *str) -{ - char *name; - - name = rsvg_get_url_string (str); - if (name) { - RsvgNode *val; - val = rsvg_defs_lookup (defs, name); - g_free (name); - - if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_CLIP_PATH) - return val; - } - return NULL; -} - static void rsvg_clip_path_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * atts) { Index: librsvg-2.40.10/rsvg-mask.h =================================================================== --- librsvg-2.40.10.orig/rsvg-mask.h +++ librsvg-2.40.10/rsvg-mask.h @@ -58,8 +58,6 @@ struct _RsvgClipPath { G_GNUC_INTERNAL RsvgNode *rsvg_new_clip_path (void); -G_GNUC_INTERNAL -RsvgNode *rsvg_clip_path_parse (const RsvgDefs * defs, const char *str); G_END_DECLS #endif Index: librsvg-2.40.10/rsvg-styles.c =================================================================== --- librsvg-2.40.10.orig/rsvg-styles.c +++ librsvg-2.40.10/rsvg-styles.c @@ -149,7 +149,7 @@ rsvg_state_init (RsvgState * state) state->visible = TRUE; state->cond_true = TRUE; state->filter = NULL; - state->clip_path_ref = NULL; + state->clip_path = NULL; state->startMarker = NULL; state->middleMarker = NULL; state->endMarker = NULL; @@ -222,6 +222,7 @@ rsvg_state_clone (RsvgState * dst, const *dst = *src; dst->parent = parent; dst->mask = g_strdup (src->mask); + dst->clip_path = g_strdup (src->clip_path); dst->font_family = g_strdup (src->font_family); dst->lang = g_strdup (src->lang); rsvg_paint_server_ref (dst->fill); @@ -356,7 +357,8 @@ rsvg_state_inherit_run (RsvgState * dst, } if (inherituninheritables) { - dst->clip_path_ref = src->clip_path_ref; + g_free (dst->clip_path); + dst->clip_path = g_strdup (src->clip_path); g_free (dst->mask); dst->mask = g_strdup (src->mask); dst->enable_background = src->enable_background; @@ -447,6 +449,7 @@ void rsvg_state_finalize (RsvgState * state) { g_free (state->mask); + g_free (state->clip_path); g_free (state->font_family); g_free (state->lang); rsvg_paint_server_unref (state->fill); @@ -524,7 +527,8 @@ rsvg_parse_style_pair (RsvgHandle * ctx, g_free (state->mask); state->mask = rsvg_get_url_string (value); } else if (g_str_equal (name, "clip-path")) { - state->clip_path_ref = rsvg_clip_path_parse (ctx->priv->defs, value); + g_free (state->clip_path); + state->clip_path = rsvg_get_url_string (value); } else if (g_str_equal (name, "overflow")) { if (!g_str_equal (value, "inherit")) { state->overflow = rsvg_css_parse_overflow (value, &state->has_overflow); Index: librsvg-2.40.10/rsvg-styles.h =================================================================== --- librsvg-2.40.10.orig/rsvg-styles.h +++ librsvg-2.40.10/rsvg-styles.h @@ -81,7 +81,7 @@ struct _RsvgState { RsvgFilter *filter; char *mask; - void *clip_path_ref; + char *clip_path; guint8 adobe_blend; /* 0..11 */ guint8 opacity; /* 0..255 */