From: Peter Rajnoha Date: Mon, 1 Nov 2010 13:31:55 +0000 (+0000) Subject: Allocate buffer for reporting functions dynamically to support long outputs. X-Git-Tag: v2_02_91~1401 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=a83c7816e4184cb6e0a9867c3381df9e11abc1fa;p=lvm2.git Allocate buffer for reporting functions dynamically to support long outputs. Fix memory leak of field_id in _output_field function. There's been a patch added recently to use dynamic allocation for metadata tags buffer to remove the 4k limit (for writing metadata out). However, when using reporting commands like vgs and lvs, we still need to fix libdm reporting functions themselves to support such long outputs. So the buffer used in those reporting functions is dynamic now. The patch also includes a fix for field_id memory leak which was found in the _output_field function. --- diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 061b89084..fbe691bdf 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,7 @@ Version 1.02.57 =================================== + Fix memory leak of field_id in _output_field function. + Allocate buffer for reporting functions dynamically to support long outputs. Version 1.02.56 - 25th October 2010 =================================== diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c index 7631e219d..951ecb3ea 100644 --- a/libdm/libdm-report.c +++ b/libdm/libdm-report.c @@ -757,7 +757,8 @@ static int _report_headings(struct dm_report *rh) { struct field_properties *fp; const char *heading; - char buf[1024]; + char *buf = NULL; + size_t buf_size = 0; if (rh->flags & RH_HEADINGS_PRINTED) return 1; @@ -773,6 +774,18 @@ static int _report_headings(struct dm_report *rh) return 0; } + dm_list_iterate_items(fp, &rh->field_props) { + if (buf_size < fp->width) + buf_size = fp->width; + } + /* Including trailing '\0'! */ + buf_size++; + + if (!(buf = dm_malloc(buf_size))) { + log_error("dm_report: Could not allocate memory for heading buffer."); + goto bad; + } + /* First heading line */ dm_list_iterate_items(fp, &rh->field_props) { if (fp->flags & FLD_HIDDEN) @@ -780,7 +793,7 @@ static int _report_headings(struct dm_report *rh) heading = rh->fields[fp->field_num].heading; if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) { - if (dm_snprintf(buf, sizeof(buf), "%-*.*s", + if (dm_snprintf(buf, buf_size, "%-*.*s", fp->width, fp->width, heading) < 0) { log_error("dm_report: snprintf heading failed"); goto bad; @@ -806,9 +819,12 @@ static int _report_headings(struct dm_report *rh) } log_print("%s", (char *) dm_pool_end_object(rh->mem)); + dm_free(buf); + return 1; bad: + dm_free(buf); dm_pool_abandon_object(rh->mem); return 0; } @@ -892,7 +908,8 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field) int32_t width; uint32_t align; const char *repstr; - char buf[4096]; + char *buf = NULL; + size_t buf_size = 0; if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) { if (!(field_id = strdup(rh->fields[field->props->field_num].id))) { @@ -902,11 +919,13 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field) if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) { log_error("dm_report: Unable to extend output line"); + free(field_id); return 0; } if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) { log_error("dm_report: Unable to extend output line"); + free(field_id); return 0; } @@ -935,25 +954,33 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field) if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK)) align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ? DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT; + + /* Including trailing '\0'! */ + buf_size = width + 1; + if (!(buf = dm_malloc(buf_size))) { + log_error("dm_report: Could not allocate memory for output line buffer."); + return 0; + } + if (align & DM_REPORT_FIELD_ALIGN_LEFT) { - if (dm_snprintf(buf, sizeof(buf), "%-*.*s", + if (dm_snprintf(buf, buf_size, "%-*.*s", width, width, repstr) < 0) { log_error("dm_report: left-aligned snprintf() failed"); - return 0; + goto bad; } if (!dm_pool_grow_object(rh->mem, buf, width)) { log_error("dm_report: Unable to extend output line"); - return 0; + goto bad; } } else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) { - if (dm_snprintf(buf, sizeof(buf), "%*.*s", + if (dm_snprintf(buf, buf_size, "%*.*s", width, width, repstr) < 0) { log_error("dm_report: right-aligned snprintf() failed"); - return 0; + goto bad; } if (!dm_pool_grow_object(rh->mem, buf, width)) { log_error("dm_report: Unable to extend output line"); - return 0; + goto bad; } } } @@ -962,10 +989,15 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field) !(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED)) if (!dm_pool_grow_object(rh->mem, "\'", 1)) { log_error("dm_report: Unable to extend output line"); - return 0; + goto bad; } + dm_free(buf); return 1; + +bad: + dm_free(buf); + return 0; } static int _output_as_rows(struct dm_report *rh)