From 7049f972404064683b156346f4267d1b5a676358 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sun, 4 Apr 2010 18:44:36 +0000 Subject: Correct management of string references in computed styles. svn path=/trunk/libcss/; revision=10240 --- src/select/computed.c | 78 ++++++++++++++++++++++++- src/select/dispatch.c | 8 +-- src/select/propset.h | 157 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 213 insertions(+), 30 deletions(-) diff --git a/src/select/computed.c b/src/select/computed.c index 72d3922..57f50cb 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -114,17 +114,69 @@ css_error css_computed_style_destroy(css_computed_style *style) if (style->uncommon != NULL) { if (style->uncommon->counter_increment != NULL) { + css_computed_counter *c; + + for (c = style->uncommon->counter_increment; + c->name != NULL; c++) { + lwc_string_unref(c->name); + } + style->alloc(style->uncommon->counter_increment, 0, style->pw); } if (style->uncommon->counter_reset != NULL) { + css_computed_counter *c; + + for (c = style->uncommon->counter_reset; + c->name != NULL; c++) { + lwc_string_unref(c->name); + } + style->alloc(style->uncommon->counter_reset, 0, style->pw); } - if (style->uncommon->cursor != NULL) + if (style->uncommon->cursor != NULL) { + lwc_string **s; + + for (s = style->uncommon->cursor; *s != NULL; s++) { + lwc_string_unref(*s); + } + style->alloc(style->uncommon->cursor, 0, style->pw); + } + + if (style->uncommon->content != NULL) { + css_computed_content_item *c; + + for (c = style->uncommon->content; + c->type != CSS_COMPUTED_CONTENT_NONE; + c++) { + switch (c->type) { + case CSS_COMPUTED_CONTENT_STRING: + lwc_string_unref(c->data.string); + break; + case CSS_COMPUTED_CONTENT_URI: + lwc_string_unref(c->data.uri); + break; + case CSS_COMPUTED_CONTENT_ATTR: + lwc_string_unref(c->data.attr); + break; + case CSS_COMPUTED_CONTENT_COUNTER: + lwc_string_unref(c->data.counter.name); + break; + case CSS_COMPUTED_CONTENT_COUNTERS: + lwc_string_unref(c->data.counters.name); + lwc_string_unref(c->data.counters.sep); + break; + default: + break; + } + } + + style->alloc(style->uncommon->content, 0, style->pw); + } style->alloc(style->uncommon, 0, style->pw); } @@ -137,11 +189,31 @@ css_error css_computed_style_destroy(css_computed_style *style) style->alloc(style->aural, 0, style->pw); } - if (style->font_family != NULL) + if (style->font_family != NULL) { + lwc_string **s; + + for (s = style->font_family; *s != NULL; s++) { + lwc_string_unref(*s); + } + style->alloc(style->font_family, 0, style->pw); + } + + if (style->quotes != NULL) { + lwc_string **s; + + for (s = style->quotes; *s != NULL; s++) { + lwc_string_unref(*s); + } - if (style->quotes != NULL) style->alloc(style->quotes, 0, style->pw); + } + + if (style->list_style_image != NULL) + lwc_string_unref(style->list_style_image); + + if (style->background_image != NULL) + lwc_string_unref(style->background_image); style->alloc(style, 0, style->pw); diff --git a/src/select/dispatch.c b/src/select/dispatch.c index 113ea0f..a0ac4aa 100644 --- a/src/select/dispatch.c +++ b/src/select/dispatch.c @@ -12,10 +12,10 @@ * Dispatch table for properties, indexed by opcode */ #define PROPERTY_FUNCS(pname) \ - cascade_##pname , \ - set_##pname##_from_hint, \ - initial_##pname , \ - compose_##pname , \ + cascade_##pname, \ + set_##pname##_from_hint, \ + initial_##pname, \ + compose_##pname, \ destroy_##pname struct prop_table prop_dispatch[CSS_N_PROPERTIES] = { diff --git a/src/select/propset.h b/src/select/propset.h index 69dba45..97d76b9 100644 --- a/src/select/propset.h +++ b/src/select/propset.h @@ -174,22 +174,32 @@ static inline css_error set_counter_increment( css_computed_counter *counters) { uint8_t *bits; + css_computed_counter *oldcounters; + css_computed_counter *c; ENSURE_UNCOMMON; bits = &style->uncommon->bits[COUNTER_INCREMENT_INDEX]; + oldcounters = style->uncommon->counter_increment; /* 1bit: type */ *bits = (*bits & ~COUNTER_INCREMENT_MASK) | ((type & 0x1) << COUNTER_INCREMENT_SHIFT); - /* Free existing array */ - if (style->uncommon->counter_increment != NULL && - style->uncommon->counter_increment != counters) - style->alloc(style->uncommon->counter_increment, 0, style->pw); + for (c = counters; c != NULL && c->name != NULL; c++) + lwc_string_ref(c->name); style->uncommon->counter_increment = counters; + /* Free existing array */ + if (oldcounters != NULL) { + for (c = oldcounters; c->name != NULL; c++) + lwc_string_unref(c->name); + + if (oldcounters != counters) + style->alloc(oldcounters, 0, style->pw); + } + return CSS_OK; } #undef COUNTER_INCREMENT_MASK @@ -204,22 +214,32 @@ static inline css_error set_counter_reset( css_computed_counter *counters) { uint8_t *bits; + css_computed_counter *oldcounters; + css_computed_counter *c; ENSURE_UNCOMMON; bits = &style->uncommon->bits[COUNTER_RESET_INDEX]; + oldcounters = style->uncommon->counter_reset; /* 1bit: type */ *bits = (*bits & ~COUNTER_RESET_MASK) | ((type & 0x1) << COUNTER_RESET_SHIFT); - /* Free existing array */ - if (style->uncommon->counter_reset != NULL && - style->uncommon->counter_reset != counters) - style->alloc(style->uncommon->counter_reset, 0, style->pw); + for (c = counters; c != NULL && c->name != NULL; c++) + lwc_string_ref(c->name); style->uncommon->counter_reset = counters; + /* Free existing array */ + if (oldcounters != NULL) { + for (c = oldcounters; c->name != NULL; c++) + lwc_string_unref(c->name); + + if (oldcounters != counters) + style->alloc(oldcounters, 0, style->pw); + } + return CSS_OK; } #undef COUNTER_RESET_MASK @@ -234,21 +254,32 @@ static inline css_error set_cursor( lwc_string **urls) { uint8_t *bits; + lwc_string **oldurls; + lwc_string **s; ENSURE_UNCOMMON; bits = &style->uncommon->bits[CURSOR_INDEX]; + oldurls = style->uncommon->cursor; /* 5bits: type */ *bits = (*bits & ~CURSOR_MASK) | ((type & 0x1f) << CURSOR_SHIFT); - /* Free existing array */ - if (style->uncommon->cursor != NULL && style->uncommon->cursor != urls) - style->alloc(style->uncommon->cursor, 0, style->pw); + for (s = urls; s != NULL && *s != NULL; s++) + lwc_string_ref(*s); style->uncommon->cursor = urls; + /* Free existing array */ + if (oldurls != NULL) { + for (s = oldurls; *s != NULL; s++) + lwc_string_unref(*s); + + if (oldurls != urls) + style->alloc(oldurls, 0, style->pw); + } + return CSS_OK; } #undef CURSOR_MASK @@ -322,22 +353,74 @@ static inline css_error set_content( css_computed_content_item *content) { uint8_t *bits; + css_computed_content_item *oldcontent; + css_computed_content_item *c; ENSURE_UNCOMMON; /* 2bits: type */ bits = &style->uncommon->bits[CONTENT_INDEX]; + oldcontent = style->uncommon->content; *bits = (*bits & ~CONTENT_MASK) | ((type & 0x3) << CONTENT_SHIFT); - /* Free existing array */ - if (style->uncommon->content != NULL && - style->uncommon->content != content) - style->alloc(style->uncommon->content, 0, style->pw); + for (c = content; c != NULL && + c->type != CSS_COMPUTED_CONTENT_NONE; c++) { + switch (c->type) { + case CSS_COMPUTED_CONTENT_STRING: + lwc_string_ref(c->data.string); + break; + case CSS_COMPUTED_CONTENT_URI: + lwc_string_ref(c->data.uri); + break; + case CSS_COMPUTED_CONTENT_ATTR: + lwc_string_ref(c->data.attr); + break; + case CSS_COMPUTED_CONTENT_COUNTER: + lwc_string_ref(c->data.counter.name); + break; + case CSS_COMPUTED_CONTENT_COUNTERS: + lwc_string_ref(c->data.counters.name); + lwc_string_ref(c->data.counters.sep); + break; + default: + break; + } + } style->uncommon->content = content; + /* Free existing array */ + if (oldcontent != NULL) { + for (c = oldcontent; + c->type != CSS_COMPUTED_CONTENT_NONE; c++) { + switch (c->type) { + case CSS_COMPUTED_CONTENT_STRING: + lwc_string_unref(c->data.string); + break; + case CSS_COMPUTED_CONTENT_URI: + lwc_string_unref(c->data.uri); + break; + case CSS_COMPUTED_CONTENT_ATTR: + lwc_string_unref(c->data.attr); + break; + case CSS_COMPUTED_CONTENT_COUNTER: + lwc_string_unref(c->data.counter.name); + break; + case CSS_COMPUTED_CONTENT_COUNTERS: + lwc_string_unref(c->data.counters.name); + lwc_string_unref(c->data.counters.sep); + break; + default: + break; + } + } + + if (oldcontent != content) + style->alloc(oldcontent, 0, style->pw); + } + return CSS_OK; } #undef CONTENT_MASK @@ -479,17 +562,21 @@ static inline css_error set_background_image( lwc_string *url) { uint8_t *bits = &style->bits[BACKGROUND_IMAGE_INDEX]; + lwc_string *oldurl = style->background_image; /* 1bit: type */ *bits = (*bits & ~BACKGROUND_IMAGE_MASK) | ((type & 0x1) << BACKGROUND_IMAGE_SHIFT); if (url != NULL) { - style->background_image = url; + style->background_image = lwc_string_ref(url); } else { style->background_image = NULL; } + if (oldurl != NULL) + lwc_string_unref(oldurl); + return CSS_OK; } #undef BACKGROUND_IMAGE_MASK @@ -525,17 +612,21 @@ static inline css_error set_list_style_image( lwc_string *url) { uint8_t *bits = &style->bits[LIST_STYLE_IMAGE_INDEX]; + lwc_string *oldurl = style->list_style_image; /* 1bit: type */ *bits = (*bits & ~LIST_STYLE_IMAGE_MASK) | ((type & 0x1) << LIST_STYLE_IMAGE_SHIFT); if (url != NULL) { - style->list_style_image = url; + style->list_style_image = lwc_string_ref(url); } else { style->list_style_image = NULL; } + if (oldurl != NULL) + lwc_string_unref(oldurl); + return CSS_OK; } #undef LIST_STYLE_IMAGE_MASK @@ -550,17 +641,27 @@ static inline css_error set_quotes( lwc_string **quotes) { uint8_t *bits = &style->bits[QUOTES_INDEX]; + lwc_string **oldquotes = style->quotes; + lwc_string **s; /* 1bit: type */ *bits = (*bits & ~QUOTES_MASK) | ((type & 0x1) << QUOTES_SHIFT); - /* Free current quotes */ - if (style->quotes != NULL && style->quotes != quotes) - style->alloc(style->quotes, 0, style->pw); + for (s = quotes; s != NULL && *s != NULL; s++) + lwc_string_ref(*s); style->quotes = quotes; + /* Free current quotes */ + if (oldquotes != NULL) { + for (s = oldquotes; *s != NULL; s++) + lwc_string_unref(*s); + + if (oldquotes != quotes) + style->alloc(oldquotes, 0, style->pw); + } + return CSS_OK; } #undef QUOTES_MASK @@ -1446,17 +1547,27 @@ static inline css_error set_font_family( lwc_string **names) { uint8_t *bits = &style->bits[FONT_FAMILY_INDEX]; + lwc_string **oldnames = style->font_family; + lwc_string **s; /* 3bits: type */ *bits = (*bits & ~FONT_FAMILY_MASK) | ((type & 0x7) << FONT_FAMILY_SHIFT); - /* Free existing families */ - if (style->font_family != NULL && style->font_family != names) - style->alloc(style->font_family, 0, style->pw); + for (s = names; s != NULL && *s != NULL; s++) + lwc_string_ref(*s); style->font_family = names; + /* Free existing families */ + if (oldnames != NULL) { + for (s = oldnames; *s != NULL; s++) + lwc_string_unref(*s); + + if (oldnames != names) + style->alloc(oldnames, 0, style->pw); + } + return CSS_OK; } #undef FONT_FAMILY_MASK -- cgit v1.2.3