]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
iovec-wrapper: fix memleak in iovw_consume() when len == 0
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 17 Apr 2026 13:52:18 +0000 (22:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 18 Apr 2026 18:45:08 +0000 (03:45 +0900)
This makes even when len == 0, the input buffer is freed.
The behavior is consistent with strv_consume() and friends.

src/basic/iovec-wrapper.c
src/test/test-iovec-wrapper.c

index a4604f9a3cbb0f20697b4bfa8d7e313fbfd17953..2b302b96ab0b29847c1bab644be16229d26260d0 100644 (file)
@@ -38,7 +38,7 @@ int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
                 return -ENOMEM;
 
         iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len);
-        return 0;
+        return 1;
 }
 
 int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) {
@@ -46,7 +46,7 @@ int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) {
         int r;
 
         r = iovw_put(iovw, data, len);
-        if (r < 0)
+        if (r <= 0)
                 free(data);
 
         return r;
index 35b939657226bd3ce9cd701ab051a26e1082339d..1f4585a129f40ff433b7f73ea9d22ad25dbaaac7 100644 (file)
@@ -38,7 +38,7 @@ TEST(iovw_append) {
         ASSERT_EQ(memcmp(iovw.iovec[0].iov_base, "one", 3), 0);
 
         /* Insert with a NUL */
-        ASSERT_OK_ZERO(iovw_append(&iovw, buf, 4));
+        ASSERT_OK(iovw_append(&iovw, buf, 4));
         ASSERT_EQ(iovw.count, 2U);
         ASSERT_EQ(iovw.iovec[1].iov_len, 4U);
         ASSERT_EQ(memcmp(iovw.iovec[1].iov_base, "one\0", 4), 0);
@@ -58,10 +58,9 @@ TEST(iovw_consume) {
         /* iovw_consume moves ownership in place, no copy */
         ASSERT_PTR_EQ(iovw.iovec[0].iov_base, p);
 
-        /* Zero-length: iovw_put returns 0 without adding anything, and does not free the payload.
-         * Confirm by strdup'ing something and explicitly freeing it afterwards. */
-        _cleanup_free_ char *q = strdup("");
-        ASSERT_NOT_NULL(q);
+        /* Zero-length: iovw_put returns 0 without adding anything. Even in that case, iovw_consume() frees
+         * the payload. Confirm by strdup'ing something to verify that when running with sanitizer/valgrind. */
+        char *q = ASSERT_NOT_NULL(strdup(""));
         ASSERT_OK_ZERO(iovw_consume(&iovw, q, 0));
         ASSERT_EQ(iovw.count, 1U);
 }