Code

Added upstream patch bts499349-memleaks.
authorSebastian Harl <sh@tokkee.org>
Thu, 25 Sep 2008 22:26:52 +0000 (00:26 +0200)
committerSebastian Harl <sh@tokkee.org>
Thu, 25 Sep 2008 22:26:52 +0000 (00:26 +0200)
This fixes a couple of memory leaks in rrdtool, librrd and the Perl and Ruby
bindings.

Closes: #499349
debian/changelog
debian/patches/bts499349-memleaks [new file with mode: 0644]
debian/patches/series

index 6d14f094c1adeab03f6a7db8aaf7b84144f48eb1..3b9b96ddc75f885656fe884ebe69c63050339943 100644 (file)
@@ -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 <sh@tokkee.org>  Fri, 26 Sep 2008 00:07:32 +0200
+ -- Sebastian Harl <sh@tokkee.org>  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 (file)
index 0000000..6b5bd77
--- /dev/null
@@ -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;
+ }
index 5a746d01cc49975882af1a4f9baff0a5432450e9..0d277c73ffa09dd282cea5f0245794a66b69fcc1 100644 (file)
@@ -7,3 +7,4 @@ implicit-decl-fix
 bts499350-data-corruption
 bts498183-segfault-madvise
 bts496847-error-handling
+bts499349-memleaks