diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-03-08 01:21:16 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-03-08 01:21:16 +0100 |
| commit | 909d716a1e6d0c03b61b2a73ad3c2bd20fa55cf2 (patch) | |
| tree | 268648d5fc0b10310b831359efc8c634c4546777 | |
| parent | 8e7557ef7a9a10781c79948afa69294afbdde10a (diff) | |
| download | dynstr-909d716a1e6d0c03b61b2a73ad3c2bd20fa55cf2.tar.gz | |
dynstr.c: Fix memory leak if realloc(3) fails
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.
| -rw-r--r-- | dynstr.c | 32 |
1 files changed, 17 insertions, 15 deletions
@@ -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 { |
