From a8d8009b7a0c2ec4f5d3097a0ae6fdb29fb0001c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 2 Jul 2026 18:37:24 +0100 Subject: [PATCH] udev: track remaining buffer size across $links devlinks FORMAT_SUBST_LINKS passes the same 'l' (remaining size) to strpcpy for each devlink and discards the returned remaining value, so the cursor advances while the bound stays at the full size, overflowing dest. Capture the return value. Follow-up for f6caab8995a27244db185f075e751a119e4bdedc --- src/udev/test-udev-format.c | 24 ++++++++++++++++++++++++ src/udev/udev-format.c | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/udev/test-udev-format.c b/src/udev/test-udev-format.c index 1acd8db72b..b71e1e182a 100644 --- a/src/udev/test-udev-format.c +++ b/src/udev/test-udev-format.c @@ -1,9 +1,13 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-device.h" + +#include "device-private.h" #include "log.h" #include "mountpoint-util.h" #include "string-util.h" #include "tests.h" +#include "udev-event.h" #include "udev-format.h" static void test_udev_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) { @@ -36,6 +40,26 @@ TEST(udev_resolve_subsys_kernel) { test_udev_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00"); } +TEST(udev_event_apply_format_links) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_(udev_event_unrefp) UdevEvent *event = NULL; + char dest[64]; + bool truncated = false; + + ASSERT_OK(sd_device_new_from_syspath(&dev, "/sys/class/net/lo")); + + for (unsigned u = 0; u < 32; u++) { + _cleanup_free_ char *l = NULL; + ASSERT_OK(asprintf(&l, "/dev/link-that-is-long-%u", u)); + ASSERT_OK(device_add_devlink(dev, l)); + } + + ASSERT_NOT_NULL((event = udev_event_new(dev, NULL, EVENT_TEST_SPAWN))); + + udev_event_apply_format(event, "$links", dest, sizeof dest, false, &truncated); + ASSERT_TRUE(truncated); +} + static int intro(void) { if (path_is_mount_point("/sys") <= 0) return log_tests_skipped("/sys is not mounted"); diff --git a/src/udev/udev-format.c b/src/udev/udev-format.c index d670ee129f..c37ea0406f 100644 --- a/src/udev/udev-format.c +++ b/src/udev/udev-format.c @@ -334,9 +334,9 @@ static ssize_t udev_event_subst_format( case FORMAT_SUBST_LINKS: FOREACH_DEVICE_DEVLINK(dev, link) { if (s == dest) - strpcpy_full(&s, l, link + STRLEN("/dev/"), &truncated); + l = strpcpy_full(&s, l, link + STRLEN("/dev/"), &truncated); else - strpcpyl_full(&s, l, &truncated, " ", link + STRLEN("/dev/"), NULL); + l = strpcpyl_full(&s, l, &truncated, " ", link + STRLEN("/dev/"), NULL); if (truncated) break; }