From 96ab986d04b9a36fdd3091dce59b5b4cf27b2e43 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Fri, 26 Sep 2008 00:26:52 +0200 Subject: [PATCH] Added upstream patch bts499349-memleaks. This fixes a couple of memory leaks in rrdtool, librrd and the Perl and Ruby bindings. Closes: #499349 --- debian/changelog | 4 +- debian/patches/bts499349-memleaks | 369 ++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 debian/patches/bts499349-memleaks diff --git a/debian/changelog b/debian/changelog index 6d14f09..3b9b96d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,11 +8,13 @@ rrdtool (1.3.1-4) unstable; urgency=low valuable debugging information (Closes: #498183). - Added upstream patch bts496847-error-handling to fix error handling of syscalls in rrdtool(1) (Closes: #496847). + - Added upstream patch bts499349-memleaks to fix a couple of memory leaks + in rrdtool, librrd and the Perl and Ruby bindings (Closes: #499349). * debian/NEWS: - Added. Documented the changes required by the switch to libpango (Closes: #493575, #493594). - -- Sebastian Harl Fri, 26 Sep 2008 00:07:32 +0200 + -- Sebastian Harl Fri, 26 Sep 2008 00:24:55 +0200 rrdtool (1.3.1-3) unstable; urgency=low diff --git a/debian/patches/bts499349-memleaks b/debian/patches/bts499349-memleaks new file mode 100644 index 0000000..6b5bd77 --- /dev/null +++ b/debian/patches/bts499349-memleaks @@ -0,0 +1,369 @@ +diff a/src/rrd_create.c b/src/rrd_create.c +--- a/src/rrd_create.c ++++ b/src/rrd_create.c +@@ -27,6 +27,9 @@ void parseGENERIC_DS( + long int rra_random_row( + rra_def_t *); + ++static void rrd_free2( ++ rrd_t *rrd); /* our onwn copy, immmune to mmap */ ++ + int rrd_create( + int argc, + char **argv) +@@ -125,15 +128,14 @@ int rrd_create_r( + /* static header */ + if ((rrd.stat_head = calloc(1, sizeof(stat_head_t))) == NULL) { + rrd_set_error("allocating rrd.stat_head"); +- free(rrd.stat_head); ++ rrd_free2(&rrd); + return (-1); + } + + /* live header */ + if ((rrd.live_head = calloc(1, sizeof(live_head_t))) == NULL) { + rrd_set_error("allocating rrd.live_head"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + +@@ -166,8 +168,7 @@ int rrd_create_r( + old_size + sizeof(ds_def_t))) == + NULL) { + rrd_set_error("allocating rrd.ds_def"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t)); +@@ -199,8 +200,7 @@ int rrd_create_r( + rrd_set_error("invalid DS format"); + } + if (rrd_test_error()) { +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return -1; + } + +@@ -223,8 +223,7 @@ int rrd_create_r( + } + + if (rrd_test_error()) { +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return -1; + } + rrd.stat_head->ds_cnt++; +@@ -238,8 +237,7 @@ int rrd_create_r( + old_size + sizeof(rra_def_t))) == + NULL) { + rrd_set_error("allocating rrd.rra_def"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0, +@@ -496,8 +494,7 @@ int rrd_create_r( + if (rrd_test_error()) { + /* all errors are unrecoverable */ + free(argvcopy); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + token = strtok_r(NULL, ":", &tokptr); +@@ -524,16 +521,14 @@ int rrd_create_r( + if (create_hw_contingent_rras(&rrd, period, hashed_name) == + -1) { + rrd_set_error("creating contingent RRA"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return -1; + } + } + rrd.stat_head->rra_cnt++; + } else { + rrd_set_error("can't parse argument '%s'", argv[i]); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return -1; + } + } +@@ -541,15 +536,13 @@ int rrd_create_r( + + if (rrd.stat_head->rra_cnt < 1) { + rrd_set_error("you must define at least one Round Robin Archive"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + + if (rrd.stat_head->ds_cnt < 1) { + rrd_set_error("you must define at least one Data Source"); +- free(rrd.stat_head); +- free(rrd.live_head); ++ rrd_free2(&rrd); + return (-1); + } + return rrd_create_fn(filename, &rrd); +@@ -618,6 +611,7 @@ int create_hw_contingent_rras( + if ((rrd->rra_def = rrd_realloc(rrd->rra_def, + old_size + 4 * sizeof(rra_def_t))) == + NULL) { ++ rrd_free2(rrd); + rrd_set_error("allocating rrd.rra_def"); + return (-1); + } +@@ -682,15 +676,15 @@ int rrd_create_fn( + int unkn_cnt; + rrd_file_t *rrd_file_dn; + rrd_t rrd_dn; +- unsigned flags = O_WRONLY | O_CREAT | O_TRUNC; ++ unsigned flags = O_WRONLY | O_CREAT | O_TRUNC; ++ + #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) + flags |= O_BINARY; + #endif + + if ((rrd_file = open(file_name, flags, 0666)) < 0) { + rrd_set_error("creating '%s': %s", file_name, rrd_strerror(errno)); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + return (-1); + } + +@@ -705,8 +699,7 @@ int rrd_create_fn( + + if ((rrd->pdp_prep = calloc(1, sizeof(pdp_prep_t))) == NULL) { + rrd_set_error("allocating pdp_prep"); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + close(rrd_file); + return (-1); + } +@@ -722,8 +715,7 @@ int rrd_create_fn( + + if ((rrd->cdp_prep = calloc(1, sizeof(cdp_prep_t))) == NULL) { + rrd_set_error("allocating cdp_prep"); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + close(rrd_file); + return (-1); + } +@@ -770,8 +762,7 @@ int rrd_create_fn( + + if ((rrd->rra_ptr = calloc(1, sizeof(rra_ptr_t))) == NULL) { + rrd_set_error("allocating rra_ptr"); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + close(rrd_file); + return (-1); + } +@@ -788,8 +779,7 @@ int rrd_create_fn( + /* write the empty data area */ + if ((unknown = (rrd_value_t *) malloc(512 * sizeof(rrd_value_t))) == NULL) { + rrd_set_error("allocating unknown"); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + close(rrd_file); + return (-1); + } +@@ -807,8 +797,7 @@ int rrd_create_fn( + } + free(unknown); + fdatasync(rrd_file); +- free(rrd->stat_head); +- free(rrd->live_head); ++ rrd_free2(rrd); + if (close(rrd_file) == -1) { + rrd_set_error("creating rrd: %s", rrd_strerror(errno)); + return -1; +@@ -821,6 +810,20 @@ int rrd_create_fn( + return (0); + } + ++ ++static void rrd_free2( ++ rrd_t *rrd) ++{ ++ free(rrd->live_head); ++ free(rrd->stat_head); ++ free(rrd->ds_def); ++ free(rrd->rra_def); ++ free(rrd->rra_ptr); ++ free(rrd->pdp_prep); ++ free(rrd->cdp_prep); ++ free(rrd->rrd_value); ++} ++ + static int rand_init = 0; + + long int rra_random_row( +diff a/src/rrd_tool.c b/src/rrd_tool.c +--- a/src/rrd_tool.c ++++ b/src/rrd_tool.c +@@ -364,6 +364,7 @@ static char *fgetslong( + return *aLinePtr = linebuf; + bufsize += MAX_LENGTH; + if (!(linebuf = realloc(linebuf, bufsize))) { ++ free(linebuf); + perror("fgetslong: realloc"); + exit(1); + } +@@ -448,6 +449,7 @@ int main( + + while (fgetslong(&aLine, stdin)) { + if ((argc = CountArgs(aLine)) == 0) { ++ free(aLine); + printf("ERROR: not enough arguments\n"); + } + if ((myargv = (char **) malloc((argc + 1) * +@@ -456,6 +458,8 @@ int main( + exit(1); + } + if ((argc = CreateArgs(argv[0], aLine, argc, myargv)) < 0) { ++ free(aLine); ++ free(myargv); + printf("ERROR: creating arguments\n"); + } else { + int ret = HandleInputLine(argc, myargv, stdout); +diff a/src/rrd_graph.c b/src/rrd_graph.c +--- a/src/rrd_graph.c ++++ b/src/rrd_graph.c +@@ -3059,6 +3059,7 @@ int graph_paint( + (im->surface, CAIRO_SVG_VERSION_1_1); + break; + }; ++ cairo_destroy(im->cr); + im->cr = cairo_create(im->surface); + cairo_set_antialias(im->cr, im->graph_antialias); + cairo_scale(im->cr, im->zoom, im->zoom); +diff a/src/rrd_gfx.c b/src/rrd_gfx.c +--- a/src/rrd_gfx.c ++++ b/src/rrd_gfx.c +@@ -158,10 +158,11 @@ static PangoLayout *gfx_prep_text( + /* pango_cairo_update_context(cr, pango_context); */ + + pango_layout_set_tabs(layout, tab_array); ++ pango_tab_array_free(tab_array); + font_desc = pango_font_description_from_string(font); + pango_font_description_set_size(font_desc, size * PANGO_SCALE); + pango_layout_set_font_description(layout, font_desc); +- ++ pango_font_description_free(font_desc); + /* pango expects the string to be utf-8 encoded */ + utf8_text = g_locale_to_utf8((const gchar *) text, -1, NULL, NULL, NULL); + +@@ -191,7 +192,6 @@ double gfx_get_text_width( + gfx_color_t color = { 0, 0, 0, 0 }; + layout = gfx_prep_text(im, start, color, font, size, tabwidth, text); + pango_layout_get_pixel_extents(layout, NULL, &log_rect); +- pango_tab_array_free(pango_layout_get_tabs(layout)); + g_object_unref(layout); + return log_rect.width; + } +@@ -252,7 +252,6 @@ void gfx_text( + pango_cairo_update_layout(cr, layout); + cairo_move_to(cr, sx, sy); + pango_cairo_show_layout(cr, layout); +- pango_tab_array_free(pango_layout_get_tabs(layout)); + g_object_unref(layout); + cairo_restore(cr); + +diff a/src/rrd_tool.c b/src/rrd_tool.c +--- a/src/rrd_tool.c ++++ b/src/rrd_tool.c +@@ -369,7 +369,11 @@ static char *fgetslong( + exit(1); + } + } +- return *aLinePtr = linebuf[0] ? linebuf : 0; ++ if (linebuf[0]){ ++ return *aLinePtr = linebuf; ++ } ++ free(linebuf); ++ return *aLinePtr = 0; + } + + int main( +diff a/bindings/perl-shared/RRDs.xs b/bindings/perl-shared/RRDs.xs +--- a/bindings/perl-shared/RRDs.xs ++++ b/bindings/perl-shared/RRDs.xs +@@ -78,8 +78,8 @@ extern "C" { + free(argv); \ + if (rrd_test_error()) XSRETURN_UNDEF; \ + hash = newHV(); \ ++ save=data; \ + while (data) { \ +- save=data; \ + /* the newSV will get copied by hv so we create it as a mortal \ + to make sure it does not keep hanging round after the fact */ \ + switch (data->type) { \ +@@ -97,18 +97,14 @@ extern "C" { + break; \ + case RD_I_STR: \ + hvs(newSVpv(data->value.u_str,0)); \ +- rrd_freemem(data->value.u_str); \ + break; \ + case RD_I_BLO: \ + hvs(newSVpv(data->value.u_blo.ptr,data->value.u_blo.size)); \ +- rrd_freemem(data->value.u_blo.ptr); \ + break; \ + } \ +- rrd_freemem(data->key); \ + data = data->next; \ +- rrd_freemem(save); \ +- } \ +- rrd_freemem(data); \ ++ } \ ++ rrd_info_free(save); \ + RETVAL = newRV_noinc((SV*)hash); + + /* +diff a/bindings/ruby/main.c b/bindings/ruby/main.c +--- a/bindings/ruby/main.c ++++ b/bindings/ruby/main.c +@@ -155,6 +155,7 @@ VALUE rb_rrd_infocall( + + RRD_CHECK_ERROR result = rb_hash_new(); + ++ p = data; + while (data) { + VALUE key = rb_str_new2(data->key); + +@@ -171,19 +172,16 @@ VALUE rb_rrd_infocall( + break; + case RD_I_STR: + rb_hash_aset(result, key, rb_str_new2(data->value.u_str)); +- rrd_freemem(data->value.u_str); + break; + case RD_I_BLO: + rb_hash_aset(result, key, + rb_str_new(data->value.u_blo.ptr, + data->value.u_blo.size)); +- rrd_freemem(data->value.u_blo.ptr); + break; + } +- p = data; + data = data->next; +- rrd_freemem(p); + } ++ rrd_info_free(p); + return result; + } + diff --git a/debian/patches/series b/debian/patches/series index 5a746d0..0d277c7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -7,3 +7,4 @@ implicit-decl-fix bts499350-data-corruption bts498183-segfault-madvise bts496847-error-handling +bts499349-memleaks -- 2.30.2