}
 
        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;
 }
 
 
 static svgtiny_code finalise_parse_state(struct svgtiny_parse_state *state)
 {
+       svgtiny_code code = svgtiny_OK;
        css_error css_code;
        svgtiny_cleanup_state_local(state);
 
                lwc_string_unref(state->interned_svg_xmlns);
        }
 
+       /* 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 fail, but we want to loop
+        * through the entire list regardless. */
+       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++) {
+               /* Note the use of (n_sheets - 1 - i) below to
+                * remove/destroy the sheets in reverse order, last-in
+                * first-out. */
+               css_code = css_select_ctx_get_sheet(state->select_ctx,
+                                                   n_sheets - 1 - i,
+                                                   &sheet);
+               if (css_code != CSS_OK) {
+                       /* The API just told us that there were n_sheets
+                        * valid sheets. So while we attempt to handle
+                        * the error gracefully in production builds,
+                        * this should never happen. */
+                       assert(0);
+                       code = svgtiny_LIBCSS_ERROR;
+                       /* If we didn't get a new sheet, don't try to
+                        * remove/destroy whatever happens to live at
+                        * the pointer. */
+                       continue;
+               }
+               /* Remove the sheets from the context as well, since
+                * there is no promise that css_select_ctx_destroy()
+                * will not try to access them. */
+               css_code = css_select_ctx_remove_sheet(state->select_ctx, sheet);
+               if (css_code != CSS_OK) {
+                       /* Same as the assert() above. This sheet arose
+                        * from a call to css_select_ctx_get_sheet() a
+                        * moment ago, it should be valid! */
+                       assert(0);
+                       code = svgtiny_LIBCSS_ERROR;
+                       /* Don't try to destroy the sheet if removal
+                        * failed, because that would suggest that our
+                        * implied contract (that nobody else modifies
+                        * our context) has been violated. */
+                       continue;
+               }
+               css_code = css_stylesheet_destroy((css_stylesheet*)sheet);
+               if (css_code != CSS_OK) {
+                       /* Once more, "sheet" should have been valid
+                        * and un-destroyed. */
+                       assert(0);
+                       code = svgtiny_LIBCSS_ERROR;
+               }
+       }
+
        css_code = css_select_ctx_destroy(state->select_ctx);
        if (css_code != CSS_OK) {
-               return svgtiny_LIBCSS_ERROR;
+               code = svgtiny_LIBCSS_ERROR;
        }
 
-       return svgtiny_OK;
+       return code;
 }