abuf: Correct a corner case with abuf_realloc()
authorSimon Glass <sjg@chromium.org>
Mon, 28 Feb 2022 19:08:22 +0000 (12:08 -0700)
committerTom Rini <trini@konsulko.com>
Wed, 6 Apr 2022 18:01:42 +0000 (14:01 -0400)
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
test/lib/abuf.c

index 4b17e0b..1635d58 100644 (file)
@@ -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;
index 086c9b2..42ee4c1 100644 (file)
@@ -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)
 {