]> gitweb.michael.orlitzky.com - libsvgtiny.git/commitdiff
src/svgtiny.c: deallocate stylesheets before destroying their context
authorMichael Orlitzky <michael@orlitzky.com>
Sun, 20 Oct 2024 15:55:16 +0000 (11:55 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Sun, 20 Oct 2024 21:58:40 +0000 (17:58 -0400)
We allocate stylesheets in svgtiny_parse_style_element() and append
them to our global select_ctx, but the select_ctx retains only a const
reference to them and is not responsible for freeing their resources.
Instead, we have to do it, right before we destroy the context itself.

This is a little ugly because we have to de-const the sheet references
before we can destroy them. This relies on the non-local knowledge
that every sheet appended to the context does in fact originate in the
one function svgtiny_parse_style_element(). On the other hand, using
the context to keep track of these sheets saves us the trouble of
maintaining a duplicate array that would differ only in type
signature.

src/svgtiny.c

index b83b766f6a7fab93bb23ee75ff6592a28d195bdb..7550610f54f906d75984019922fc8856be2bda45 100644 (file)
@@ -786,9 +786,30 @@ cleanup:
        dom_node_unref(svg);
        dom_node_unref(document);
 
-       /* Only override the true exit code with a failure from this
-        * "destroy" if a more meaningful error code is not already
-        * set. */
+       /* Clean up the select_ctx and any sheets that were appended
+        * to it along the way.  These sheets are allocated in
+        * svgtiny_parse_style_element(), and the only references we
+        * have to them are the ones in state.select_ctx->sheets.
+        * Those are const, but we are indeed responsible for the
+        * resources, so the un-const cast below is kosher.
+        *
+        * Some of these destructors can technically fail, but we only
+        * override the exit code with a failure from a destructor if
+        * a more meaningful error code is not already set. */
+       unsigned int i;
+       uint32_t n_sheets;
+       const css_stylesheet* sheet;
+       css_select_ctx_count_sheets(state.select_ctx, &n_sheets);
+       for (i = 0; i < n_sheets; i++) {
+               css_code = css_select_ctx_get_sheet(state.select_ctx, i, &sheet);
+               if (css_code != CSS_OK && code == svgtiny_OK) {
+                 code = svgtiny_LIBCSS_ERROR;
+               }
+               css_code = css_stylesheet_destroy((css_stylesheet*)sheet);
+               if (css_code != CSS_OK && code == svgtiny_OK) {
+                 code = svgtiny_LIBCSS_ERROR;
+               }
+       }
        css_code = css_select_ctx_destroy(state.select_ctx);
        if (css_code != CSS_OK && code == svgtiny_OK) {
                code = svgtiny_LIBCSS_ERROR;
@@ -876,6 +897,11 @@ svgtiny_code svgtiny_parse_style_element(dom_element *style,
        }
 
        dom_string_unref(data);
+
+       /* The only reference we retain to the newly-allocated "sheet"
+        * is via state.select_ctx->sheets. Eventually, we will
+        * destroy the sheet immediately prior to destroying the
+        * context. */
        return svgtiny_OK;
 }