summaryrefslogtreecommitdiff
path: root/lib/vasnprintf.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2021-06-05 15:44:26 +0200
committerBruno Haible <bruno@clisp.org>2021-06-05 15:44:26 +0200
commit4d288a80bf7ebe29334b9805cdcc70eacb6059c1 (patch)
treecaafe710caa933335251b0c659026b7552812550 /lib/vasnprintf.c
parentf3553bdefc9202e81996c73686e3ca53cd827417 (diff)
downloadgnulib-4d288a80bf7ebe29334b9805cdcc70eacb6059c1.tar.gz
vasnprintf: Don't leak memory when memory allocation fails.
Found by Coverity. Reported by Mike Fabian <mfabian@redhat.com> in <https://lists.gnu.org/archive/html/bug-libunistring/2021-06/msg00000.html>. * lib/vasnprintf.c (VASNPRINTF): In places where a local variable points to heap-allocated storage, free that storage before doing 'goto out_of_memory;'.
Diffstat (limited to 'lib/vasnprintf.c')
-rw-r--r--lib/vasnprintf.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index f859fc40bc..089c113533 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -1924,7 +1924,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* Ensures that allocated >= needed. Aborts through a jump to
out_of_memory if needed is SIZE_MAX or otherwise too big. */
-#define ENSURE_ALLOCATION(needed) \
+#define ENSURE_ALLOCATION_ELSE(needed, oom_statement) \
if ((needed) > allocated) \
{ \
size_t memory_size; \
@@ -1935,17 +1935,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
allocated = (needed); \
memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
if (size_overflow_p (memory_size)) \
- goto out_of_memory; \
+ oom_statement \
if (result == resultbuf || result == NULL) \
memory = (DCHAR_T *) malloc (memory_size); \
else \
memory = (DCHAR_T *) realloc (result, memory_size); \
if (memory == NULL) \
- goto out_of_memory; \
+ oom_statement \
if (result == resultbuf && length > 0) \
DCHAR_CPY (memory, result, length); \
result = memory; \
}
+#define ENSURE_ALLOCATION(needed) \
+ ENSURE_ALLOCATION_ELSE((needed), goto out_of_memory; )
for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
{
@@ -2193,7 +2195,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
if (converted != result + length)
{
- ENSURE_ALLOCATION (xsum (length, converted_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
+ { free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
@@ -2317,7 +2320,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
if (converted != result + length)
{
- ENSURE_ALLOCATION (xsum (length, converted_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
+ { free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
@@ -2441,7 +2445,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
if (converted != result + length)
{
- ENSURE_ALLOCATION (xsum (length, converted_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
+ { free (converted); goto out_of_memory; });
DCHAR_CPY (result + length, converted, converted_len);
free (converted);
}
@@ -2944,7 +2949,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
# else
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
+ { free (tmpdst); goto out_of_memory; });
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
length += tmpdst_len;
@@ -3147,7 +3153,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
# else
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
+ { free (tmpdst); goto out_of_memory; });
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
length += tmpdst_len;
@@ -5598,7 +5605,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
CLEANUP ();
return NULL;
}
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+ ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
+ { free (tmpdst); goto out_of_memory; });
DCHAR_CPY (result + length, tmpdst, tmpdst_len);
free (tmpdst);
count = tmpdst_len;