diff mbox series

[05/18] abuf: Correct a corner case with abuf_realloc()

Message ID 20220228190835.1480772-6-sjg@chromium.org
State Accepted
Commit 99aca9efe10c005189b47160d178d18f14301c7e
Delegated to: Tom Rini
Headers show
Series Various bugfixes related to verified boot | expand

Commit Message

Simon Glass Feb. 28, 2022, 7:08 p.m. UTC
If the buffer is empty and not allocated, then abuf_realloc() tries to
copy invalid data. This happens because an incorrect change to use
memdup() was added after the original code was written.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/abuf.c      |  4 +++-
 test/lib/abuf.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/lib/abuf.c b/lib/abuf.c
index 4b17e0b8c0..1635d58682 100644
--- a/lib/abuf.c
+++ b/lib/abuf.c
@@ -51,9 +51,11 @@  bool abuf_realloc(struct abuf *abuf, size_t new_size)
 		/* not currently allocated and new size is larger. Alloc and
 		 * copy in data. The new space is not inited.
 		 */
-		ptr = memdup(abuf->data, new_size);
+		ptr = malloc(new_size);
 		if (!ptr)
 			return false;
+		if (abuf->size)
+			memcpy(ptr, abuf->data, abuf->size);
 		abuf->data = ptr;
 		abuf->size = new_size;
 		abuf->alloced = true;
diff --git a/test/lib/abuf.c b/test/lib/abuf.c
index 086c9b2282..42ee4c1755 100644
--- a/test/lib/abuf.c
+++ b/test/lib/abuf.c
@@ -126,6 +126,35 @@  static int lib_test_abuf_realloc(struct unit_test_state *uts)
 }
 LIB_TEST(lib_test_abuf_realloc, 0);
 
+/* Test abuf_realloc() on an non-allocated buffer of zero size */
+static int lib_test_abuf_realloc_size(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	ulong start;
+
+	start = ut_check_free();
+
+	abuf_init(&buf);
+
+	/* Allocate some space */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
+	ut_assertnonnull(buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(true, buf.alloced);
+
+	/* Free it */
+	ut_asserteq(true, abuf_realloc(&buf, 0));
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Check for memory leaks */
+	ut_assertok(ut_check_delta(start));
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_realloc_size, 0);
+
 /* Test handling of buffers that are too large */
 static int lib_test_abuf_large(struct unit_test_state *uts)
 {