changeset 676:2730e7a80abd

val: don't leak val references on val_alloc_array_dup error If the array allocation failed, we leaked all the struct val references passed in. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sun, 24 Feb 2019 10:36:28 -0500
parents cf7308f74b62
children 94be6289538b
files val_array.c
diffstat 1 files changed, 27 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/val_array.c	Sun Feb 24 10:38:23 2019 -0500
+++ b/val_array.c	Sun Feb 24 10:36:28 2019 -0500
@@ -25,11 +25,34 @@
 #include "val_impl.h"
 
 static struct val *__val_alloc_array(struct val **vals, size_t nelem,
-				     bool heap)
+				     bool dup, bool heap)
 {
 	struct val *val;
 	size_t i;
 
+	if (dup) {
+		struct val **tmp;
+
+		/* no reason to ever duplicate a heap allocated array */
+		ASSERT(!heap);
+
+		tmp = mem_reallocarray(NULL, nelem, sizeof(struct val *));
+		if (!tmp) {
+			val = ERR_PTR(-ENOMEM);
+			goto err;
+		}
+
+		/*
+		 * The multiplication can't overflow since the memory allocation
+		 * already checks for it.
+		 */
+		memcpy(tmp, vals, sizeof(struct val *) * nelem);
+
+		/* switch to the new array & free it on error or 0 refcnt */
+		vals = tmp;
+		heap = true;
+	}
+
 	val = __val_alloc(VT_ARRAY);
 	if (IS_ERR(val))
 		goto err;
@@ -52,27 +75,15 @@
 
 struct val *val_alloc_array(struct val **vals, size_t nelem)
 {
-	return __val_alloc_array(vals, nelem, true);
+	return __val_alloc_array(vals, nelem, false, true);
 }
 
 struct val *val_alloc_array_dup(struct val **vals, size_t nelem)
 {
-	struct val **tmp;
-
-	tmp = mem_reallocarray(NULL, nelem, sizeof(struct val *));
-	if (!tmp)
-		return ERR_PTR(-ENOMEM);
-
-	/*
-	 * The multiplication can't overflow since the memory allocation
-	 * already checks for it.
-	 */
-	memcpy(tmp, vals, sizeof(struct val *) * nelem);
-
-	return __val_alloc_array(tmp, nelem, true);
+	return __val_alloc_array(vals, nelem, true, false);
 }
 
 struct val *val_alloc_array_static(struct val **vals, size_t nelem)
 {
-	return __val_alloc_array(vals, nelem, false);
+	return __val_alloc_array(vals, nelem, false, false);
 }