[librsvg/librsvg-2.40: 5/10] NodeUse: fix infinite loops due to recursive references of "use" elements
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/librsvg-2.40: 5/10] NodeUse: fix infinite loops due to recursive references of "use" elements
- Date: Wed, 26 Feb 2020 17:43:20 +0000 (UTC)
commit 5ac08d4f6eec4753656607ff94504110a2812e7b
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Feb 26 11:22:42 2020 -0600
NodeUse: fix infinite loops due to recursive references of "use" elements
rsvg-structure.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
---
diff --git a/rsvg-structure.c b/rsvg-structure.c
index 823a91b4..d31e6d50 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -183,6 +183,7 @@ static void
rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
RsvgNodeUse *use = (RsvgNodeUse *) self;
+ RsvgNode *self_acquired = NULL;
RsvgNode *child;
RsvgState *state;
cairo_matrix_t affine;
@@ -194,14 +195,26 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
rsvg_state_reinherit_top (ctx, self->state, dominate);
- if (use->link == NULL)
- return;
+ /* <use> is an element that is used directly, unlike
+ * <pattern>, which is used through a fill="url(#...)"
+ * reference. However, <use> will always reference another
+ * element, potentially itself or an ancestor of itself (or
+ * another <use> which references the first one, etc.). So,
+ * we acquire the <use> element itself so that circular
+ * references can be caught.
+ */
+ self_acquired = rsvg_drawing_ctx_acquire_node_ref (ctx, self);
+ if (!self_acquired) {
+ goto out;
+ }
+
+ if (use->link == NULL) {
+ goto out;
+ }
+
child = rsvg_acquire_node (ctx, use->link);
- if (!child)
- return;
- else if (rsvg_node_is_ancestor (child, self)) { /* or, if we're <use>'ing ourself */
- rsvg_release_node (ctx, child);
- return;
+ if (!child) {
+ goto out;
}
state = rsvg_current_state (ctx);
@@ -254,6 +267,12 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
rsvg_release_node (ctx, child);
}
+
+out:
+
+ if (self_acquired) {
+ rsvg_release_node (ctx, self_acquired);
+ }
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]