From 909d716a1e6d0c03b61b2a73ad3c2bd20fa55cf2 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Wed, 8 Mar 2023 01:21:16 +0100 Subject: [PATCH] dynstr.c: Fix memory leak if realloc(3) fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to C99 ยง7.20.3.4: If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged. Therefore, a temporary pointer must be used to ensure the original object can still be deallocated should realloc(3) return a null pointer. --- dynstr.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/dynstr.c b/dynstr.c index 3d75f26..f7a89ee 100644 --- a/dynstr.c +++ b/dynstr.c @@ -40,13 +40,13 @@ enum dynstr_err dynstr_vappend(struct dynstr *const d, const char *const format, { const size_t src_len = vsnprintf(NULL, 0, format, ap); const size_t new_len = d->len + src_len + 1; + char *const s = realloc(d->str, new_len * sizeof *d->str); - d->str = realloc(d->str, new_len * sizeof *d->str); - - if (d->str) + if (s) { - vsprintf(d->str + d->len, format, apc); + vsprintf(s + d->len, format, apc); d->len += src_len; + d->str = s; } else { @@ -79,25 +79,26 @@ enum dynstr_err dynstr_vprepend(struct dynstr *const d, const char *const format { const size_t src_len = vsnprintf(NULL, 0, format, ap); const size_t new_len = d->len + src_len + 1; + char *const s = realloc(d->str, new_len * sizeof *d->str); - d->str = realloc(d->str, new_len * sizeof *d->str); - - if (d->str && d->len) + if (s && d->len) { /* Keep byte that will be removed by later call to vsprintf. */ - const char c = *d->str; + const char c = *s; for (size_t i = new_len - 1, j = d->len; j <= d->len; i--, j--) { - d->str[i] = d->str[j]; + s[i] = s[j]; } - vsprintf(d->str, format, apc); - d->str[src_len] = c; + vsprintf(s, format, apc); + s[src_len] = c; + d->str = s; } else if (!d->len) { - vsprintf(d->str + d->len, format, apc); + vsprintf(s + d->len, format, apc); + d->str = s; } else { @@ -128,12 +129,13 @@ enum dynstr_err dynstr_dup(struct dynstr *const dst, const struct dynstr *const if (src->len && src->str) { const size_t sz = (src->len + 1) * sizeof *dst->str; - dst->str = realloc(dst->str, sz); + char *const s = realloc(dst->str, sz); - if (dst->str) + if (s) { - memcpy(dst->str, src->str, sz); + memcpy(s, src->str, sz); dst->len = src->len; + dst->str = s; } else {