]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: track remaining buffer size across $links devlinks
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 2 Jul 2026 17:37:24 +0000 (18:37 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 6 Jul 2026 12:42:21 +0000 (13:42 +0100)
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
src/udev/udev-format.c

index 1acd8db72bf9b55f84fa53492b89a48c0138ae1b..b71e1e182a1ba756c40e37f71a65f5d03a53524b 100644 (file)
@@ -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");
index d670ee129fdd91572a767745f203d58d1152fb34..c37ea0406f9b9ed4876c067e9fa2833c9a3c22d6 100644 (file)
@@ -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;
                 }