Tuesday, 3 March 2015

libcss memory leak

#pragma hdrstop
#pragma argsused

#include <stdio.h>
#include <tchar.h>

#include <libcss/libcss.h>

css_error resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
{
/* About as useless as possible */
*abs = lwc_string_ref(rel);
return CSS_OK;
}

void check(const css_error code) {
if (code != CSS_OK && code != CSS_NEEDDATA ) {
printf ("Error\n");
}
}

int _tmain(int argc, _TCHAR* argv[])
{
css_error code;
css_stylesheet *sheet;
size_t size;
const char data[] =
"h1 { color: red } "
"h4 { color: #321; } "
"h4, h5 { color: #123456; }";
css_stylesheet_params params;

printf("%d", __BORLANDC__);

params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
params.level = CSS_LEVEL_21;
params.charset = "UTF-8";
params.url = "foo";
params.title = "foo";
params.allow_quirks = false;
params.inline_style = false;
params.resolve = resolve_url;
params.resolve_pw = NULL;
params.import = NULL;
params.import_pw = NULL;
params.color = NULL;
params.color_pw = NULL;
params.font = NULL;
params.font_pw = NULL;

printf ("sizeof(bool) = %d\n", sizeof(bool));

/* create a stylesheet */

code = css_stylesheet_create(&params, &sheet);
check(code);

code = css_stylesheet_size(sheet, &size);
check(code);

printf("created stylesheet, size %d\n", size);

/* parse some CSS source */

code = css_stylesheet_append_data(sheet, (const uint8_t *) data, sizeof data);
check(code);

// code = css_stylesheet_data_done(sheet);
// check(code);

code = css_stylesheet_destroy(sheet);
check(code);

lwc_finalize();

return 0;
}libcss may leak memory if css_stylesheet_data_done() is not called. See the attached source for an example.

One might argue that css_stylesheet_data_done() is a mandatory call, but I believe that a library should try to avoid memory leaks as much as possible.

Hence I propose fix below which adds a single line to css_error css__parser_destroy(). I am not sure if this is the most elegant solution, but it works well for me.

Feedback from the libcss developers is much appreciated.

Ralf

----

css_error css__parser_destroy(css_parser *parser)
{
if (parser == NULL)
return CSS_BADPARM;

parserutils_stack_destroy(parser->open_items);

unref_interned_strings_in_tokens(parser); /* <-- added: Memory leak otherwise. */
parserutils_vector_destroy(parser->tokens);

parserutils_stack_destroy(parser->states);

css__lexer_destroy(parser->lexer);

parserutils_inputstream_destroy(parser->stream);

free(parser);

return CSS_OK;
}

No comments:

Post a Comment