| From 6cfaab12c70cd4a34c4730837f1ecdf792593c90 Mon Sep 17 00:00:00 2001 |
| From: Benjamin Otte <otte@redhat.com> |
| 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 <akuster@mvista.com> |
| |
| --- |
| 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 */ |
| |