Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 1 | From 6cfaab12c70cd4a34c4730837f1ecdf792593c90 Mon Sep 17 00:00:00 2001 |
| 2 | From: Benjamin Otte <otte@redhat.com> |
| 3 | Date: Wed, 7 Oct 2015 07:57:39 +0200 |
| 4 | Subject: [PATCH] state: Look up clip path lazily |
| 5 | |
| 6 | Upstream-status: Backport |
| 7 | |
| 8 | supporting patch |
| 9 | https://git.gnome.org/browse/librsvg/commit/rsvg-styles.c?id=6cfaab12c70cd4a34c4730837f1ecdf792593c90 |
| 10 | |
| 11 | CVE: CVE-2015-7558 |
| 12 | Signed-off-by: Armin Kuster <akuster@mvista.com> |
| 13 | |
| 14 | --- |
| 15 | rsvg-cairo-draw.c | 56 +++++++++++++++++++++++++++++++++---------------------- |
| 16 | rsvg-mask.c | 17 ----------------- |
| 17 | rsvg-mask.h | 2 -- |
| 18 | rsvg-styles.c | 10 +++++++--- |
| 19 | rsvg-styles.h | 2 +- |
| 20 | 5 files changed, 42 insertions(+), 45 deletions(-) |
| 21 | |
| 22 | Index: librsvg-2.40.10/rsvg-cairo-draw.c |
| 23 | =================================================================== |
| 24 | --- librsvg-2.40.10.orig/rsvg-cairo-draw.c |
| 25 | +++ librsvg-2.40.10/rsvg-cairo-draw.c |
| 26 | @@ -461,7 +461,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * |
| 27 | return; |
| 28 | |
| 29 | need_tmpbuf = ((state->fill != NULL) && (state->stroke != NULL) && state->opacity != 0xff) |
| 30 | - || state->clip_path_ref || state->mask || state->filter |
| 31 | + || state->clip_path || state->mask || state->filter |
| 32 | || (state->comp_op != CAIRO_OPERATOR_OVER); |
| 33 | |
| 34 | if (need_tmpbuf) |
| 35 | @@ -708,18 +708,6 @@ rsvg_cairo_generate_mask (cairo_t * cr, |
| 36 | } |
| 37 | |
| 38 | static void |
| 39 | -rsvg_cairo_push_early_clips (RsvgDrawingCtx * ctx) |
| 40 | -{ |
| 41 | - RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); |
| 42 | - |
| 43 | - cairo_save (render->cr); |
| 44 | - if (rsvg_current_state (ctx)->clip_path_ref) |
| 45 | - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == userSpaceOnUse) |
| 46 | - rsvg_cairo_clip (ctx, rsvg_current_state (ctx)->clip_path_ref, NULL); |
| 47 | - |
| 48 | -} |
| 49 | - |
| 50 | -static void |
| 51 | rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx) |
| 52 | { |
| 53 | /* XXX: Untested, probably needs help wrt filters */ |
| 54 | @@ -731,9 +719,27 @@ rsvg_cairo_push_render_stack (RsvgDrawin |
| 55 | RsvgState *state = rsvg_current_state (ctx); |
| 56 | gboolean lateclip = FALSE; |
| 57 | |
| 58 | - if (rsvg_current_state (ctx)->clip_path_ref) |
| 59 | - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == objectBoundingBox) |
| 60 | - lateclip = TRUE; |
| 61 | + if (rsvg_current_state (ctx)->clip_path) { |
| 62 | + RsvgNode *node; |
| 63 | + node = rsvg_defs_lookup (ctx->defs, rsvg_current_state (ctx)->clip_path); |
| 64 | + if (node && RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CLIP_PATH) { |
| 65 | + RsvgClipPath *clip_path = (RsvgClipPath *) node; |
| 66 | + |
| 67 | + switch (clip_path->units) { |
| 68 | + case userSpaceOnUse: |
| 69 | + rsvg_cairo_clip (ctx, clip_path, NULL); |
| 70 | + break; |
| 71 | + case objectBoundingBox: |
| 72 | + lateclip = TRUE; |
| 73 | + break; |
| 74 | + |
| 75 | + default: |
| 76 | + g_assert_not_reached (); |
| 77 | + break; |
| 78 | + } |
| 79 | + |
| 80 | + } |
| 81 | + } |
| 82 | |
| 83 | if (state->opacity == 0xFF |
| 84 | && !state->filter && !state->mask && !lateclip && (state->comp_op == CAIRO_OPERATOR_OVER) |
| 85 | @@ -774,7 +780,9 @@ rsvg_cairo_push_render_stack (RsvgDrawin |
| 86 | void |
| 87 | rsvg_cairo_push_discrete_layer (RsvgDrawingCtx * ctx) |
| 88 | { |
| 89 | - rsvg_cairo_push_early_clips (ctx); |
| 90 | + RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); |
| 91 | + |
| 92 | + cairo_save (render->cr); |
| 93 | rsvg_cairo_push_render_stack (ctx); |
| 94 | } |
| 95 | |
| 96 | @@ -783,14 +791,18 @@ rsvg_cairo_pop_render_stack (RsvgDrawing |
| 97 | { |
| 98 | RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render); |
| 99 | cairo_t *child_cr = render->cr; |
| 100 | - gboolean lateclip = FALSE; |
| 101 | + RsvgClipPath *lateclip = NULL; |
| 102 | cairo_surface_t *surface = NULL; |
| 103 | RsvgState *state = rsvg_current_state (ctx); |
| 104 | gboolean nest; |
| 105 | |
| 106 | - if (rsvg_current_state (ctx)->clip_path_ref) |
| 107 | - if (((RsvgClipPath *) rsvg_current_state (ctx)->clip_path_ref)->units == objectBoundingBox) |
| 108 | - lateclip = TRUE; |
| 109 | + if (rsvg_current_state (ctx)->clip_path) { |
| 110 | + RsvgNode *node; |
| 111 | + node = rsvg_defs_lookup (ctx->defs, rsvg_current_state (ctx)->clip_path); |
| 112 | + if (node && RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CLIP_PATH |
| 113 | + && ((RsvgClipPath *) node)->units == objectBoundingBox) |
| 114 | + lateclip = (RsvgClipPath *) node; |
| 115 | + } |
| 116 | |
| 117 | if (state->opacity == 0xFF |
| 118 | && !state->filter && !state->mask && !lateclip && (state->comp_op == CAIRO_OPERATOR_OVER) |
| 119 | @@ -820,7 +832,7 @@ rsvg_cairo_pop_render_stack (RsvgDrawing |
| 120 | nest ? 0 : render->offset_y); |
| 121 | |
| 122 | if (lateclip) |
| 123 | - rsvg_cairo_clip (ctx, rsvg_current_state (ctx)->clip_path_ref, &render->bbox); |
| 124 | + rsvg_cairo_clip (ctx, lateclip, &render->bbox); |
| 125 | |
| 126 | cairo_set_operator (render->cr, state->comp_op); |
| 127 | |
| 128 | Index: librsvg-2.40.10/rsvg-mask.c |
| 129 | =================================================================== |
| 130 | --- librsvg-2.40.10.orig/rsvg-mask.c |
| 131 | +++ librsvg-2.40.10/rsvg-mask.c |
| 132 | @@ -102,23 +102,6 @@ rsvg_get_url_string (const char *str) |
| 133 | return NULL; |
| 134 | } |
| 135 | |
| 136 | -RsvgNode * |
| 137 | -rsvg_clip_path_parse (const RsvgDefs * defs, const char *str) |
| 138 | -{ |
| 139 | - char *name; |
| 140 | - |
| 141 | - name = rsvg_get_url_string (str); |
| 142 | - if (name) { |
| 143 | - RsvgNode *val; |
| 144 | - val = rsvg_defs_lookup (defs, name); |
| 145 | - g_free (name); |
| 146 | - |
| 147 | - if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_CLIP_PATH) |
| 148 | - return val; |
| 149 | - } |
| 150 | - return NULL; |
| 151 | -} |
| 152 | - |
| 153 | static void |
| 154 | rsvg_clip_path_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * atts) |
| 155 | { |
| 156 | Index: librsvg-2.40.10/rsvg-mask.h |
| 157 | =================================================================== |
| 158 | --- librsvg-2.40.10.orig/rsvg-mask.h |
| 159 | +++ librsvg-2.40.10/rsvg-mask.h |
| 160 | @@ -58,8 +58,6 @@ struct _RsvgClipPath { |
| 161 | |
| 162 | G_GNUC_INTERNAL |
| 163 | RsvgNode *rsvg_new_clip_path (void); |
| 164 | -G_GNUC_INTERNAL |
| 165 | -RsvgNode *rsvg_clip_path_parse (const RsvgDefs * defs, const char *str); |
| 166 | |
| 167 | G_END_DECLS |
| 168 | #endif |
| 169 | Index: librsvg-2.40.10/rsvg-styles.c |
| 170 | =================================================================== |
| 171 | --- librsvg-2.40.10.orig/rsvg-styles.c |
| 172 | +++ librsvg-2.40.10/rsvg-styles.c |
| 173 | @@ -149,7 +149,7 @@ rsvg_state_init (RsvgState * state) |
| 174 | state->visible = TRUE; |
| 175 | state->cond_true = TRUE; |
| 176 | state->filter = NULL; |
| 177 | - state->clip_path_ref = NULL; |
| 178 | + state->clip_path = NULL; |
| 179 | state->startMarker = NULL; |
| 180 | state->middleMarker = NULL; |
| 181 | state->endMarker = NULL; |
| 182 | @@ -222,6 +222,7 @@ rsvg_state_clone (RsvgState * dst, const |
| 183 | *dst = *src; |
| 184 | dst->parent = parent; |
| 185 | dst->mask = g_strdup (src->mask); |
| 186 | + dst->clip_path = g_strdup (src->clip_path); |
| 187 | dst->font_family = g_strdup (src->font_family); |
| 188 | dst->lang = g_strdup (src->lang); |
| 189 | rsvg_paint_server_ref (dst->fill); |
| 190 | @@ -356,7 +357,8 @@ rsvg_state_inherit_run (RsvgState * dst, |
| 191 | } |
| 192 | |
| 193 | if (inherituninheritables) { |
| 194 | - dst->clip_path_ref = src->clip_path_ref; |
| 195 | + g_free (dst->clip_path); |
| 196 | + dst->clip_path = g_strdup (src->clip_path); |
| 197 | g_free (dst->mask); |
| 198 | dst->mask = g_strdup (src->mask); |
| 199 | dst->enable_background = src->enable_background; |
| 200 | @@ -447,6 +449,7 @@ void |
| 201 | rsvg_state_finalize (RsvgState * state) |
| 202 | { |
| 203 | g_free (state->mask); |
| 204 | + g_free (state->clip_path); |
| 205 | g_free (state->font_family); |
| 206 | g_free (state->lang); |
| 207 | rsvg_paint_server_unref (state->fill); |
| 208 | @@ -524,7 +527,8 @@ rsvg_parse_style_pair (RsvgHandle * ctx, |
| 209 | g_free (state->mask); |
| 210 | state->mask = rsvg_get_url_string (value); |
| 211 | } else if (g_str_equal (name, "clip-path")) { |
| 212 | - state->clip_path_ref = rsvg_clip_path_parse (ctx->priv->defs, value); |
| 213 | + g_free (state->clip_path); |
| 214 | + state->clip_path = rsvg_get_url_string (value); |
| 215 | } else if (g_str_equal (name, "overflow")) { |
| 216 | if (!g_str_equal (value, "inherit")) { |
| 217 | state->overflow = rsvg_css_parse_overflow (value, &state->has_overflow); |
| 218 | Index: librsvg-2.40.10/rsvg-styles.h |
| 219 | =================================================================== |
| 220 | --- librsvg-2.40.10.orig/rsvg-styles.h |
| 221 | +++ librsvg-2.40.10/rsvg-styles.h |
| 222 | @@ -81,7 +81,7 @@ struct _RsvgState { |
| 223 | |
| 224 | RsvgFilter *filter; |
| 225 | char *mask; |
| 226 | - void *clip_path_ref; |
| 227 | + char *clip_path; |
| 228 | guint8 adobe_blend; /* 0..11 */ |
| 229 | guint8 opacity; /* 0..255 */ |
| 230 | |