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 f6caab8995
This commit is contained in:
Luca Boccassi
2026-07-06 13:42:21 +01:00
parent 7003a9bf09
commit a8d8009b7a
2 changed files with 26 additions and 2 deletions
+24
View 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");
+2 -2
View 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;
}