blob: 9f6820ef9bb8b040fbbee624672c659e3577b20b [file] [log] [blame]
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 */